@beeos-ai/cli 1.0.16 → 1.0.18

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beeos-ai/cli",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
4
4
  "type": "module",
5
5
  "description": "BeeOS CLI — run AI agents from your desktop",
6
6
  "bin": {
@@ -1,40 +1,65 @@
1
1
  {
2
2
  "$comment": [
3
- "P1-E of the install-link review (shared anchor file).",
3
+ "Existing-install copy lint anchor (was P1-E of the install-link review).",
4
4
  "",
5
- "Three call sites render the 'BeeOS is already installed — what now?'",
6
- "menu with subtly different copy:",
5
+ "## Historical context",
7
6
  "",
8
- " 1. web/packages/cli/scripts/install.sh (bash, pre-Node)",
9
- " 2. web/packages/cli/scripts/install.ps1 (PowerShell, pre-Node)",
10
- " 3. web/packages/cli/src/commands/init.ts (TS, post-Node)",
7
+ "Before CLI 1.0.18 the same 'BeeOS is already installed — what now?'",
8
+ "menu was rendered from THREE places — install.sh, install.ps1, and",
9
+ "init.ts and this manifest enforced shared keyword wording across",
10
+ "all three. The bash + PowerShell sites can't import TypeScript",
11
+ "constants, so a vitest grep lint",
12
+ "(`web/packages/cli/src/__tests__/existing-install-actions.test.ts`)",
13
+ "kept the three menus from drifting apart.",
11
14
  "",
12
- "Pre-Node sites can't import TypeScript constants, so we anchor the",
13
- "wording with this manifest plus a vitest grep lint",
14
- "(`web/packages/cli/src/__tests__/existing-install-actions.test.ts`).",
15
- "If you change a label in any of the three files, update the",
16
- "matching `keywords` here so the lint stays representative; if you",
17
- "add a new action altogether, add a new entry below + render it",
18
- "in all three sites."
15
+ "## CLI 1.0.18 simplification",
16
+ "",
17
+ "The bootstrap scripts (install.sh / install.ps1) are now framework-",
18
+ "agnostic: their only job is `detect Node + npm i -g @beeos-ai/cli +",
19
+ "exec beeos init`. They no longer render any menu — 'what to do",
20
+ "when BeeOS is already installed' is `beeos init`'s job, where the",
21
+ "user sees the upgrade / rebind / reset-all / skip choices.",
22
+ "",
23
+ "Consequence: the cross-site copy alignment lint shrinks to a",
24
+ "**single-file** lint on detect.ts. install.sh and install.ps1 are",
25
+ "removed from `files`. The `actions` block stays as a sanity check",
26
+ "that detect.ts's `initDecisionLabel` keeps recognisable terminology",
27
+ "(Upgrade / Re-bind / Skip).",
28
+ "",
29
+ "The `advisory` block (added in 1.0.17 for the soft-rebind / reset-all",
30
+ "split) is preserved and still pins the must-appear-in copy on",
31
+ "detect.ts so users can tell the two rebind variants apart from the",
32
+ "label alone."
19
33
  ],
20
34
  "actions": {
21
35
  "upgrade": {
22
- "$comment": "Reinstall the CLI to the latest version, then proceed. install.sh/install.ps1 wording differs slightly from init.ts which says 'Upgrade CLI & agents'; both must hit at least one keyword from `keywords`.",
23
- "keywords": ["Reinstall", "Upgrade"]
36
+ "$comment": "detect.ts 'Upgrade CLI & agents' label.",
37
+ "keywords": ["Upgrade"]
24
38
  },
25
39
  "rerun": {
26
- "$comment": "Reuse the existing install (no npm i -g). install.sh/install.ps1 say 'Re-run beeos init', init.ts shows the 'Re-bind' wording for the same conceptual action.",
27
- "keywords": ["Re-run", "Re-bind", "Reusing"]
40
+ "$comment": "detect.ts soft-rebind label includes 'Re-bind'; advisory block below pins the full phrasing.",
41
+ "keywords": ["Re-bind", "Reusing"]
28
42
  },
29
43
  "skip": {
30
- "$comment": "Do nothing. Stable wording across all three sites.",
44
+ "$comment": "Stable across releases.",
31
45
  "keywords": ["Skip"]
32
46
  }
33
47
  },
34
- "$files_root_comment": "Paths below are relative to the `web/` workspace root (the test resolves them against that anchor).",
48
+ "$files_root_comment": "Path is relative to the `web/` workspace root (the test resolves it against that anchor).",
35
49
  "files": [
36
- "packages/cli/scripts/install.sh",
37
- "packages/cli/scripts/install.ps1",
38
50
  "packages/core/src/detect.ts"
39
- ]
51
+ ],
52
+ "$advisory_comment": "Strings below are advisory — not enforced by the lint, but checked by `existing-install-actions.test.ts` to make sure detect.ts's two rebind variants stay distinguishable from each other.",
53
+ "advisory": {
54
+ "rebind_soft": {
55
+ "$comment": "1.0.17+ : detect.ts must include this exact phrase so users see the soft-rebind keeps the same instance_id.",
56
+ "must_appear_in": ["packages/core/src/detect.ts"],
57
+ "keywords": ["keep key, refresh binding", "same instance"]
58
+ },
59
+ "rebind_destructive": {
60
+ "$comment": "1.0.17+ : detect.ts must include this phrase so the destructive rebind is unmistakable.",
61
+ "must_appear_in": ["packages/core/src/detect.ts"],
62
+ "keywords": ["NEW key", "NEW instance"]
63
+ }
64
+ }
40
65
  }
@@ -23,18 +23,24 @@
23
23
 
24
24
  # ── Parse-time checks ────────────────────────────────────────
25
25
 
26
- $scriptPath = Join-Path $PSScriptRoot "install.ps1"
26
+ # Pester 5 runs file-level code in the discovery phase but does NOT
27
+ # propagate vars defined there into It blocks at run phase. Compute
28
+ # the path inside each test (or via BeforeAll) so $scriptPath is
29
+ # always non-null when the assertions execute.
30
+ BeforeAll {
31
+ $script:ScriptPath = Join-Path $PSScriptRoot "install.ps1"
32
+ }
27
33
 
28
34
  Describe "install.ps1 parse-time integrity" {
29
35
  It "exists at the expected path" {
30
- Test-Path $scriptPath | Should -Be $true
36
+ Test-Path $script:ScriptPath | Should -Be $true
31
37
  }
32
38
 
33
39
  It "parses without syntax errors (AST round-trip)" {
34
40
  $tokens = $null
35
41
  $errors = $null
36
42
  [System.Management.Automation.Language.Parser]::ParseFile(
37
- $scriptPath,
43
+ $script:ScriptPath,
38
44
  [ref]$tokens,
39
45
  [ref]$errors
40
46
  ) | Out-Null
@@ -45,7 +51,7 @@ Describe "install.ps1 parse-time integrity" {
45
51
  $tokens = $null
46
52
  $errors = $null
47
53
  $ast = [System.Management.Automation.Language.Parser]::ParseFile(
48
- $scriptPath,
54
+ $script:ScriptPath,
49
55
  [ref]$tokens,
50
56
  [ref]$errors
51
57
  )
@@ -55,6 +61,12 @@ Describe "install.ps1 parse-time integrity" {
55
61
  $node -is [System.Management.Automation.Language.FunctionDefinitionAst]
56
62
  }, $true) | ForEach-Object { $_.Name }
57
63
 
64
+ # CLI >= 1.0.16: Install-DeviceAgentSuite has been removed —
65
+ # the device suite installs lazily on the first
66
+ # `beeos device attach` (see core/device-setup.ts).
67
+ # CLI >= 1.0.18: Read-ExistingInstallAction + Get-BeeosVersion
68
+ # are gone — `beeos init` is the single owner of the
69
+ # already-installed menu, the bootstrap script just hands off.
58
70
  $expected = @(
59
71
  "Write-BeeInfo",
60
72
  "Write-BeeOk",
@@ -65,8 +77,6 @@ Describe "install.ps1 parse-time integrity" {
65
77
  "Install-NodeAuto",
66
78
  "Show-InstallHints",
67
79
  "Send-Telemetry",
68
- "Read-ExistingInstallAction",
69
- "Install-DeviceAgentSuite",
70
80
  "Invoke-BeeosCli",
71
81
  # P2-8: PSCore + RunAs auto-elevation helpers.
72
82
  "Test-IsAdministrator",
@@ -83,7 +93,7 @@ Describe "install.ps1 parse-time integrity" {
83
93
 
84
94
  Describe "install.ps1 platform guard (P2-8)" {
85
95
  It "contains the non-Windows early-exit branch" {
86
- $content = Get-Content -Raw -Path $scriptPath
96
+ $content = Get-Content -Raw -Path $script:ScriptPath
87
97
  # Look for the marker comment AND the exit branch so a
88
98
  # superficial rename of the variable still trips the test.
89
99
  $content | Should -Match "This installer is Windows-only"
@@ -91,12 +101,12 @@ Describe "install.ps1 platform guard (P2-8)" {
91
101
  }
92
102
 
93
103
  It "contains a UAC auto-elevation branch" {
94
- $content = Get-Content -Raw -Path $scriptPath
104
+ $content = Get-Content -Raw -Path $script:ScriptPath
95
105
  $content | Should -Match "Start-Process .* -Verb RunAs"
96
106
  }
97
107
 
98
108
  It "honours BEEOS_NO_AUTO_ELEVATE=1 as an opt-out" {
99
- $content = Get-Content -Raw -Path $scriptPath
109
+ $content = Get-Content -Raw -Path $script:ScriptPath
100
110
  $content | Should -Match "BEEOS_NO_AUTO_ELEVATE"
101
111
  }
102
112
  }
@@ -106,13 +116,16 @@ Describe "install.ps1 stdin / TTY handover (P1-J)" {
106
116
  # prompts read from the exhausted pipe and silently take defaults.
107
117
  # Mirrors install.sh's `</dev/tty` reattachment.
108
118
  It "detects [Console]::IsInputRedirected" {
109
- $content = Get-Content -Raw -Path $scriptPath
119
+ $content = Get-Content -Raw -Path $script:ScriptPath
110
120
  $content | Should -Match "\[Console\]::IsInputRedirected"
111
121
  }
112
122
 
113
123
  It "uses Start-Process with -NoNewWindow when stdin is redirected" {
114
- $content = Get-Content -Raw -Path $scriptPath
115
- $content | Should -Match "Start-Process .* -NoNewWindow"
124
+ $content = Get-Content -Raw -Path $script:ScriptPath
125
+ # The Start-Process invocation in install.ps1 uses backtick line
126
+ # continuation, so `-NoNewWindow` lives on a separate line from
127
+ # `Start-Process`. `(?s)` enables dotall so `.` matches newlines.
128
+ $content | Should -Match "(?s)Start-Process .*?-NoNewWindow"
116
129
  }
117
130
  }
118
131
 
@@ -121,25 +134,29 @@ Describe "install.ps1 stderr log file (P1-I)" {
121
134
  # MUST land in a forensic file instead of `2>$null`. The lint
122
135
  # below is structural — assert the variable + the redirect appear.
123
136
  It "declares a `$BeeosInstallLog` variable" {
124
- $content = Get-Content -Raw -Path $scriptPath
137
+ $content = Get-Content -Raw -Path $script:ScriptPath
125
138
  $content | Should -Match "BeeosInstallLog"
126
139
  }
127
140
 
128
141
  It "redirects winget stderr to the install log" {
129
- $content = Get-Content -Raw -Path $scriptPath
142
+ $content = Get-Content -Raw -Path $script:ScriptPath
130
143
  # `2>>$BeeosInstallLog` is the canonical append-redirect syntax;
131
144
  # `2>$null` here would be a regression to the silent
132
145
  # behaviour the review called out.
133
- $content | Should -Match "winget install [^`r`n]+2>>\$BeeosInstallLog"
146
+ # Use a single-quoted string so `$BeeosInstallLog` is NOT
147
+ # subject to PowerShell variable interpolation; the .NET regex
148
+ # engine still treats `\r` / `\n` as CR / LF and `\$` as a
149
+ # literal `$`.
150
+ $content | Should -Match 'winget install [^\r\n]+2>>\$BeeosInstallLog'
134
151
  }
135
152
 
136
153
  It "redirects choco stderr to the install log" {
137
- $content = Get-Content -Raw -Path $scriptPath
138
- $content | Should -Match "choco install [^`r`n]+2>>\$BeeosInstallLog"
154
+ $content = Get-Content -Raw -Path $script:ScriptPath
155
+ $content | Should -Match 'choco install [^\r\n]+2>>\$BeeosInstallLog'
139
156
  }
140
157
 
141
158
  It "Show-InstallHints surfaces the log path on failure" {
142
- $content = Get-Content -Raw -Path $scriptPath
159
+ $content = Get-Content -Raw -Path $script:ScriptPath
143
160
  $content | Should -Match "Installer log:"
144
161
  }
145
162
  }
@@ -164,6 +181,6 @@ Describe "install.ps1 dry-run hook" {
164
181
  # Dot-source so we exercise the param-block + helper definitions
165
182
  # without invoking the main install body. The dry-run hook
166
183
  # `return`s before any state-changing call.
167
- { . $scriptPath } | Should -Not -Throw
184
+ { . $script:ScriptPath } | Should -Not -Throw
168
185
  }
169
186
  }
@@ -4,35 +4,28 @@
4
4
  BeeOS CLI Installer for Windows.
5
5
 
6
6
  .DESCRIPTION
7
- Detects or installs Node.js (via winget / Chocolatey fallback), then
8
- dispatches into `beeos init` (default) or `beeos device attach` when
9
- `-Device` is passed. Heavier deps (Python, uv, adb, scrcpy/vnc bridges)
10
- are installed lazily by the CLI itself.
11
-
12
- Staging / dev-loop env vars (CLI >= 1.0.10). All four are inherited by
13
- the spawned `beeos init` / `beeos device attach` child via the normal
14
- process env passthrough no extra Set-Item / -PassThru is needed. CLI
15
- >= 1.0.10 reads them via the loadOrCreateConfig env-overrides layer;
16
- older CLIs only honor BEEOS_API_URL (telemetry) +
17
- BEEOS_AGENT_GATEWAY_URL (runtime).
18
-
19
- $env:BEEOS_API_URL Public API base; both this script
20
- (telemetry) and the CLI runtime use
21
- this.
22
- $env:BEEOS_AGENT_GATEWAY_URL Agent Gateway base (Ed25519-signed
23
- bootstrap requests).
24
- $env:BEEOS_DASHBOARD_URL Dashboard base (OAuth + bind redirect).
25
- $env:BEEOS_DEVICE_AGENT_VERSION Pin @beeos-ai/device-agent semver.
26
- $env:BEEOS_MCP_SERVER_VERSION Pin @beeos-ai/device-mcp-server semver.
27
- $env:BEEOS_USE_NPX = "1" Power-user escape hatch: use `npx`
28
- for a throwaway install. `beeos`
29
- will NOT persist on PATH after
30
- the script exits. Default
31
- behaviour (since CLI 1.0.11) is
32
- always `npm install -g` so the
33
- CLI plus the device-agent suite
34
- are both globally available for
35
- follow-up commands.
7
+ Responsibilities (deliberately minimal framework-agnostic):
8
+ 1. Detect or install Node.js (via winget / Chocolatey fallback).
9
+ 2. `npm install -g @beeos-ai/cli`.
10
+ 3. `exec beeos init` (or `beeos device attach` with `-Device`).
11
+
12
+ Anything else "you already have BeeOS installed, what now?",
13
+ framework selection, rebind variants lives inside the CLI's own
14
+ `beeos init` menu, not here. The bootstrap script stays small so
15
+ it's easy to maintain and easy to diagnose on a customer machine.
16
+
17
+ Optional env vars:
18
+
19
+ $env:BEEOS_API_URL Public API base (this script uses
20
+ it for telemetry; the CLI uses it
21
+ for runtime). Defaults to production.
22
+ $env:BEEOS_AGENT_GATEWAY_URL Agent Gateway base (forwarded as-is
23
+ to the spawned CLI).
24
+ $env:BEEOS_DASHBOARD_URL Dashboard base (OAuth / bind redirect).
25
+ $env:BEEOS_INSTALL_DRY_RUN=1 CI smoke-test escape hatch.
26
+ $env:BEEOS_NO_TELEMETRY=1 Disable script-level telemetry POSTs.
27
+ $env:BEEOS_USE_NPX = "1" Power-user throwaway install (beeos
28
+ won't persist on PATH).
36
29
 
37
30
  .EXAMPLE
38
31
  # One-liner (PowerShell 5+):
@@ -40,19 +33,17 @@
40
33
 
41
34
  .EXAMPLE
42
35
  # With specific CLI version:
43
- .\install.ps1 -Version 1.0.4
36
+ .\install.ps1 -Version 1.0.18
44
37
 
45
38
  .EXAMPLE
46
39
  # Jump straight into device attach instead of init:
47
40
  .\install.ps1 -Device
48
41
 
49
42
  .EXAMPLE
50
- # Bare-metal one-shot staging install (CLI >= 1.0.11):
43
+ # Bare-metal staging one-liner:
51
44
  $env:BEEOS_API_URL = "https://public-api-staging.beeos.ai"
52
45
  $env:BEEOS_AGENT_GATEWAY_URL = "https://agent-gw-staging.beeos.ai"
53
46
  $env:BEEOS_DASHBOARD_URL = "https://beeos-staging-web.vercel.app"
54
- $env:BEEOS_DEVICE_AGENT_VERSION = "0.4.2"
55
- $env:BEEOS_MCP_SERVER_VERSION = "0.2.3"
56
47
  irm https://beeos.ai/install.ps1 | iex
57
48
  #>
58
49
  param(
@@ -102,18 +93,11 @@ if (-not $script:IsWindowsHost) {
102
93
 
103
94
  $CliPackage = if ($Version -eq "latest") { "@beeos-ai/cli@latest" } else { "@beeos-ai/cli@$Version" }
104
95
 
105
- # Sibling packages installed alongside the CLI so that `beeos device attach`
106
- # works on a clean machine without further `npm i -g` steps (a.k.a. the
107
- # "fleet ready" install strategy see agents/device-agent/ARCHITECTURE.md
108
- # for the 0.2.0+ sibling-pair topology between device-agent and
109
- # device-mcp-server). Versions are independent of `-Version` (which only
110
- # pins the CLI) — both packages follow their own semver. Override via
111
- # $env:BEEOS_DEVICE_AGENT_VERSION / $env:BEEOS_MCP_SERVER_VERSION when you
112
- # need to pin a specific build (e.g. for a staging smoke test).
113
- $DeviceAgentVersion = if ($env:BEEOS_DEVICE_AGENT_VERSION) { $env:BEEOS_DEVICE_AGENT_VERSION } else { "latest" }
114
- $McpServerVersion = if ($env:BEEOS_MCP_SERVER_VERSION) { $env:BEEOS_MCP_SERVER_VERSION } else { "latest" }
115
- $DeviceAgentPackage = "@beeos-ai/device-agent@$DeviceAgentVersion"
116
- $McpServerPackage = "@beeos-ai/device-mcp-server@$McpServerVersion"
96
+ # `@beeos-ai/device-agent` + `@beeos-ai/device-mcp-server` are NOT
97
+ # installed here. CLI >= 1.0.16 installs them lazily on the first
98
+ # `beeos device attach` via `ensureDeviceAgent` in
99
+ # `web/packages/core/src/device-setup.ts`. OpenClaw-only users never
100
+ # download the device suite at all.
117
101
 
118
102
  # Telemetry endpoint (override with $env:BEEOS_API_URL for staging).
119
103
  if (-not $env:BEEOS_API_URL -or $env:BEEOS_API_URL.Length -eq 0) {
@@ -426,92 +410,6 @@ function Show-InstallHints {
426
410
  }
427
411
  }
428
412
 
429
- # ── Existing install detection ───────────────────────────────
430
-
431
- function Get-BeeosVersion {
432
- try {
433
- $out = & beeos --version 2>$null
434
- if ($out) {
435
- if ($out -match "\d+\.\d+\.\d+") { return $Matches[0] }
436
- return ($out -replace '\s+','')
437
- }
438
- } catch {}
439
- return $null
440
- }
441
-
442
- function Read-ExistingInstallAction {
443
- # Note on naming: "Reinstall + upgrade CLI" deliberately differs
444
- # from the `beeos init` menu's "Upgrade CLI & agents" item. The
445
- # script-side action also re-bootstraps Node / pnpm and re-applies
446
- # this shell's env vars before exec'ing the new binary, which the
447
- # in-CLI upgrade does NOT do — choosing a different verb keeps the
448
- # two flows distinguishable. See `install.sh` for the matching
449
- # docstring.
450
- #
451
- # P1-E of the install-link review: the labels rendered below are
452
- # anchored against `install.sh::prompt_existing_install_action` +
453
- # `init.ts::decideAction` via
454
- # `web/packages/cli/scripts/_existing_install_actions.json` and
455
- # the vitest grep lint at
456
- # `web/packages/cli/src/__tests__/existing-install-actions.test.ts`.
457
- # Keep at least one keyword from `keywords[action]` per option.
458
- $ver = Get-BeeosVersion
459
- if (-not $ver) { $ver = "unknown" }
460
- Write-BeeWarn "BeeOS CLI is already installed (v$ver)."
461
- Write-Host ""
462
- Write-Host " [1] Reinstall + upgrade CLI to the latest version, then run beeos init"
463
- Write-Host " [2] Re-run beeos init without reinstalling"
464
- Write-Host " [3] Skip (do nothing)"
465
- Write-Host ""
466
-
467
- if (-not [Environment]::UserInteractive) {
468
- Write-BeeInfo "Non-interactive shell — defaulting to reinstall."
469
- return "upgrade"
470
- }
471
-
472
- $choice = Read-Host "Choose [1-3]"
473
- switch ($choice) {
474
- "" { return "upgrade" }
475
- "1" { return "upgrade" }
476
- "2" { return "rerun" }
477
- "3" { return "skip" }
478
- default { return "upgrade" }
479
- }
480
- }
481
-
482
- # ── Device-agent sibling suite installer ─────────────────────
483
- #
484
- # Installs `@beeos-ai/device-agent` + `@beeos-ai/device-mcp-server` globally
485
- # so the very first `beeos device attach` on a clean machine does not need
486
- # to fetch them separately. `@beeos-ai/device-common` is pulled
487
- # transitively as a `dependencies` entry of both — no separate install
488
- # needed.
489
- #
490
- # Failure here is NEVER fatal: the CLI itself was already installed
491
- # successfully, and `beeos device attach` will prompt to install missing
492
- # pieces via ensureDeviceAgent on first use. We just emit a WARN with the
493
- # manual recovery command.
494
- function Install-DeviceAgentSuite {
495
- $npmPath = Get-Command npm -ErrorAction SilentlyContinue
496
- if (-not $npmPath) {
497
- Write-BeeWarn "npm not available — skipping device-agent suite install."
498
- Write-BeeWarn "Manual fix: install Node + run ``npm i -g $DeviceAgentPackage $McpServerPackage``."
499
- return
500
- }
501
-
502
- Write-BeeInfo "Installing device-agent suite ($DeviceAgentPackage, $McpServerPackage)..."
503
- & npm install -g $DeviceAgentPackage $McpServerPackage
504
- if ($LASTEXITCODE -eq 0) {
505
- Write-BeeOk "device-agent suite installed."
506
- } else {
507
- Write-BeeWarn "Failed to install device-agent suite — ``beeos device attach`` will prompt for it on first use."
508
- Write-BeeWarn "Manual fix: npm i -g $DeviceAgentPackage $McpServerPackage"
509
- # Reset $LASTEXITCODE so subsequent `if ($LASTEXITCODE -ne 0)` checks
510
- # in callers don't trip on this non-fatal failure.
511
- $global:LASTEXITCODE = 0
512
- }
513
- }
514
-
515
413
  # ── Run CLI ──────────────────────────────────────────────────
516
414
 
517
415
  function Invoke-BeeosCli {
@@ -547,9 +445,7 @@ function Invoke-BeeosCli {
547
445
  if ($LASTEXITCODE -ne 0) {
548
446
  # P0-A of the install-link review: fail-after-bootstrap signal.
549
447
  # The `install.bootstrap.cli_installed` event is only emitted
550
- # AFTER npm + the device-agent suite report success, so npm
551
- # failures are recorded as a distinct outcome (not as silent
552
- # post-success).
448
+ # AFTER npm reports success.
553
449
  Send-Telemetry -Event "install.bootstrap.npm_fail" -ErrorCode "npm_install_cli_failed" -Success $false
554
450
  Write-BeeError "npm install -g $CliPackage failed."
555
451
  Write-BeeError ""
@@ -559,7 +455,10 @@ function Invoke-BeeosCli {
559
455
  Write-BeeError " - EACCES / permission error: run PowerShell as Administrator"
560
456
  exit 1
561
457
  }
562
- Install-DeviceAgentSuite
458
+ # Device-agent suite is intentionally NOT installed here; `beeos
459
+ # device attach` will auto-install it on first use via
460
+ # `ensureDeviceAgent` (see `web/packages/core/src/device-setup.ts`).
461
+ # OpenClaw-only users never download those ~20MB.
563
462
  Send-Telemetry -Event "install.bootstrap.cli_installed"
564
463
 
565
464
  # P1-J of the install-link review: when the user invokes the
@@ -641,34 +540,11 @@ if (-not (Test-NodeVersion)) {
641
540
  $nodeVer = & node -v
642
541
  Write-BeeOk "Node.js $nodeVer detected"
643
542
 
644
- $beeosCmd = Get-Command beeos -ErrorAction SilentlyContinue
645
- if ($beeosCmd) {
646
- $action = Read-ExistingInstallAction
647
- switch ($action) {
648
- "skip" {
649
- Write-BeeInfo "Skipping. Run `beeos init` or `beeos device attach` manually later."
650
- exit 0
651
- }
652
- "upgrade" {
653
- Write-BeeInfo "Reinstalling $CliPackage..."
654
- & npm install -g $CliPackage
655
- if ($LASTEXITCODE -ne 0) {
656
- Send-Telemetry -Event "install.bootstrap.npm_fail" -ErrorCode "npm_install_cli_failed_upgrade" -Success $false
657
- Write-BeeError "npm install -g $CliPackage failed."
658
- Write-BeeError ""
659
- Write-BeeError "Common fixes:"
660
- Write-BeeError " - EEXIST on beeos from another package:"
661
- Write-BeeError " npm uninstall -g beeos # then re-run installer"
662
- Write-BeeError " - EACCES / permission error: run PowerShell as Administrator"
663
- exit 1
664
- }
665
- Install-DeviceAgentSuite
666
- }
667
- "rerun" {
668
- Write-BeeInfo "Reusing existing install."
669
- }
670
- }
671
- }
543
+ # Bootstrap is finished. Hand off to `Invoke-BeeosCli` which performs
544
+ # `npm install -g @beeos-ai/cli` (idempotent — npm short-circuits when
545
+ # the requested version is already on disk) and then runs the freshly
546
+ # installed binary. "What does the CLI do when it's already installed?"
547
+ # is now `beeos init`'s problem; we don't second-guess it from out here.
672
548
 
673
549
  Write-BeeInfo "Running BeeOS CLI..."
674
550
  Write-Host ""