kaizenai 0.5.0 → 0.6.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.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/kaizenai.svg?style=flat&colorA=18181b&colorB=f472b6)](https://www.npmjs.com/package/kaizenai)
4
4
 
5
- Local first, browser based PDE (Product Development Environment) useClaude Code, Codex, Gemini, and Cursor on any browser. Pair this with Tailscale to have your development machine in any browser in the world.
5
+ Local first, browser based PDE (Product Development Environment) for Claude Code, Codex, Gemini, and Cursor. Run `kaizen --remote` to bind on your Tailscale network, print a QR handoff URL, and jump from your phone or tablet into the same workspace.
6
6
 
7
7
  ## Quickstart
8
8
 
@@ -45,6 +45,8 @@ kaizen --no-open
45
45
 
46
46
  Default URL: `http://localhost:3210`
47
47
 
48
+ `kaizen --remote` keeps local browser access on `localhost`, resolves your stable Tailscale host, and prints a QR code for the mobile handoff page at `/open`.
49
+
48
50
  ## Requirements
49
51
 
50
52
  - [Bun](https://bun.sh) v1.3.5+
package/bin/kaizen CHANGED
@@ -1,11 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { existsSync, realpathSync } from "node:fs"
4
- import { spawn } from "node:child_process"
4
+ import { spawn, spawnSync } from "node:child_process"
5
5
  import path from "node:path"
6
6
  import process from "node:process"
7
7
  import { fileURLToPath } from "node:url"
8
8
 
9
+ const CLI_COMMAND = "kaizen"
10
+
9
11
  function failBunMissing() {
10
12
  console.error("Kaizen requires Bun 1.3.5+ to run.")
11
13
  console.error("Install Bun from https://bun.sh and then retry.")
@@ -14,28 +16,66 @@ function failBunMissing() {
14
16
 
15
17
  const binPath = realpathSync(fileURLToPath(import.meta.url))
16
18
  const packageRoot = path.dirname(path.dirname(binPath))
19
+ const launcherPath = process.argv[1] ? path.resolve(process.argv[1]) : binPath
20
+
21
+ function hasCommandOnPath(command) {
22
+ const lookupCommand = process.platform === "win32" ? "where" : "which"
23
+ const result = spawnSync(lookupCommand, [command], { stdio: "ignore" })
24
+ return result.status === 0
25
+ }
17
26
 
18
27
  function resolveEntrypoint(kind) {
19
- const builtPath = path.join(packageRoot, "dist", "server", kind === "child" ? "cli.js" : "cli-supervisor.js")
20
- const sourcePath = path.join(packageRoot, "src", "server", kind === "child" ? "cli.ts" : "cli-supervisor.ts")
28
+ const builtPath = path.join(
29
+ packageRoot,
30
+ "dist",
31
+ "server",
32
+ kind === "child" ? "cli.js" : "cli-supervisor.js"
33
+ )
34
+ const sourcePath = path.join(
35
+ packageRoot,
36
+ "src",
37
+ "server",
38
+ kind === "child" ? "cli.ts" : "cli-supervisor.ts"
39
+ )
21
40
  return existsSync(builtPath) ? builtPath : sourcePath
22
41
  }
23
42
 
24
- const entrypoint = process.env.KAIZEN_CLI_MODE === "child"
25
- ? resolveEntrypoint("child")
26
- : resolveEntrypoint("supervisor")
43
+ function resolveChildProcessSpec() {
44
+ if (hasCommandOnPath(CLI_COMMAND)) {
45
+ return {
46
+ command: CLI_COMMAND,
47
+ args: [],
48
+ }
49
+ }
50
+
51
+ return {
52
+ command: process.execPath,
53
+ args: [launcherPath],
54
+ }
55
+ }
56
+
57
+ const entrypoint =
58
+ process.env.KAIZEN_CLI_MODE === "child"
59
+ ? resolveEntrypoint("child")
60
+ : resolveEntrypoint("supervisor")
61
+ const childProcess = resolveChildProcessSpec()
27
62
 
28
63
  const child = spawn("bun", [entrypoint, ...process.argv.slice(2)], {
29
64
  stdio: "inherit",
30
65
  env: {
31
66
  ...process.env,
32
- KAIZEN_CLI_CHILD_COMMAND: process.execPath,
33
- KAIZEN_CLI_CHILD_ARGS: JSON.stringify([binPath]),
67
+ KAIZEN_CLI_CHILD_COMMAND: childProcess.command,
68
+ KAIZEN_CLI_CHILD_ARGS: JSON.stringify(childProcess.args),
34
69
  },
35
70
  })
36
71
 
37
72
  child.on("error", (error) => {
38
- if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
73
+ if (
74
+ error &&
75
+ typeof error === "object" &&
76
+ "code" in error &&
77
+ error.code === "ENOENT"
78
+ ) {
39
79
  failBunMissing()
40
80
  return
41
81
  }