@polderlabs/bizar 6.2.4 → 6.3.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/.claude/CLAUDE.md +15 -0
- package/.claude/agents/_shared/AGENT_BASELINE.md +168 -0
- package/.claude/agents/_shared/CLAUDE_TOOLS.md +412 -0
- package/.claude/agents/_shared/SKILLS.md +109 -0
- package/.claude/agents/agent-browser.md +80 -0
- package/.claude/agents/baldr.md +49 -0
- package/.claude/agents/forseti.md +51 -0
- package/.claude/agents/frigg.md +42 -0
- package/.claude/agents/heimdall.md +33 -0
- package/.claude/agents/hermod.md +53 -0
- package/.claude/agents/mimir.md +49 -0
- package/.claude/agents/odin.md +287 -0
- package/.claude/agents/quick.md +34 -0
- package/.claude/agents/semble-search.md +50 -0
- package/.claude/agents/thor.md +53 -0
- package/.claude/agents/tyr.md +56 -0
- package/.claude/agents/vidarr.md +54 -0
- package/.claude/agents/vor.md +53 -0
- package/.claude/commands/audit.md +25 -0
- package/.claude/commands/bizar.md +22 -0
- package/.claude/commands/explain.md +17 -0
- package/.claude/commands/init.md +29 -0
- package/.claude/commands/learn.md +44 -0
- package/.claude/commands/plan.md +35 -0
- package/.claude/commands/plow-through.md +50 -0
- package/.claude/commands/pr-review.md +49 -0
- package/.claude/commands/setup-provider.md +96 -0
- package/.claude/commands/tailscale-serve.md +100 -0
- package/.claude/commands/team.md +132 -0
- package/.claude/commands/test.md +62 -0
- package/.claude/commands/validate.md +68 -0
- package/.claude/commands/visual-plan.md +24 -0
- package/.claude/hooks/README.md +92 -0
- package/.claude/hooks/posttooluse-editwrite.mjs +91 -0
- package/.claude/hooks/pretooluse-bash.mjs +81 -0
- package/.claude/hooks/pretooluse-editwrite.mjs +139 -0
- package/.claude/hooks/sessionend-recall.mjs +74 -0
- package/.claude/hooks/sessionstart-prime.mjs +80 -0
- package/.claude/hooks/userpromptsubmit-tag.mjs +80 -0
- package/.claude/settings.json +116 -0
- package/.claude/skills/9router/SKILL.md +80 -0
- package/.claude/skills/9router-chat/SKILL.md +73 -0
- package/.claude/skills/9router-embeddings/SKILL.md +69 -0
- package/.claude/skills/9router-image/SKILL.md +86 -0
- package/.claude/skills/9router-stt/SKILL.md +79 -0
- package/.claude/skills/9router-tts/SKILL.md +80 -0
- package/.claude/skills/9router-web-fetch/SKILL.md +99 -0
- package/.claude/skills/9router-web-search/SKILL.md +91 -0
- package/.claude/skills/bizar/README.md +9 -0
- package/.claude/skills/bizar/SKILL.md +450 -0
- package/.claude/skills/cpp-coding-standards/README.md +28 -0
- package/.claude/skills/cpp-coding-standards/SKILL.md +634 -0
- package/.claude/skills/cpp-coding-standards/references/concurrency.md +320 -0
- package/.claude/skills/cpp-coding-standards/references/error-handling.md +229 -0
- package/.claude/skills/cpp-coding-standards/references/memory-safety.md +216 -0
- package/.claude/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
- package/.claude/skills/cpp-coding-standards/references/review-checklist.md +96 -0
- package/.claude/skills/cpp-testing/README.md +28 -0
- package/.claude/skills/cpp-testing/SKILL.md +304 -0
- package/.claude/skills/cpp-testing/references/coverage.md +370 -0
- package/.claude/skills/cpp-testing/references/framework-compare.md +175 -0
- package/.claude/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
- package/.claude/skills/cpp-testing/references/mocking.md +364 -0
- package/.claude/skills/cpp-testing/references/tdd-workflow.md +308 -0
- package/.claude/skills/cubesandbox/SKILL.md +148 -0
- package/.claude/skills/embedded-esp-idf/README.md +41 -0
- package/.claude/skills/embedded-esp-idf/SKILL.md +439 -0
- package/.claude/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
- package/.claude/skills/embedded-esp-idf/references/host-tests.md +164 -0
- package/.claude/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
- package/.claude/skills/embedded-esp-idf/references/kconfig.md +159 -0
- package/.claude/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
- package/.claude/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
- package/.claude/skills/embedded-esp-idf/references/nvs.md +121 -0
- package/.claude/skills/embedded-esp-idf/references/packed-structs.md +192 -0
- package/.claude/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
- package/.claude/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
- package/.claude/skills/glyph/SKILL.md +163 -0
- package/.claude/skills/harness-engineering/SKILL.md +143 -0
- package/.claude/skills/lightrag/SKILL.md +81 -0
- package/.claude/skills/memory-protocol/SKILL.md +105 -0
- package/.claude/skills/obsidian/SKILL.md +306 -0
- package/.claude/skills/read-the-damn-docs/SKILL.md +113 -0
- package/.claude/skills/self-improvement/SKILL.md +64 -0
- package/README.md +87 -59
- package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js → EnvVarsSection-B58aiJiE.js} +1 -1
- package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js.map → EnvVarsSection-B58aiJiE.js.map} +1 -1
- package/bizar-dash/dist/assets/{MobileChat-BnKN_Ks_.js → MobileChat-BJrqwVDd.js} +1 -1
- package/bizar-dash/dist/assets/{MobileChat-BnKN_Ks_.js.map → MobileChat-BJrqwVDd.js.map} +1 -1
- package/bizar-dash/dist/assets/{MobileSettings-DjCPxC-Q.js → MobileSettings-CEQNJNLJ.js} +1 -1
- package/bizar-dash/dist/assets/{MobileSettings-DjCPxC-Q.js.map → MobileSettings-CEQNJNLJ.js.map} +1 -1
- package/bizar-dash/dist/assets/{main-DYiZqMrn.js → main-IvfQAOfy.js} +1 -1
- package/bizar-dash/dist/assets/{main-DYiZqMrn.js.map → main-IvfQAOfy.js.map} +1 -1
- package/bizar-dash/dist/assets/{markdown-C6mXtQxD.js → markdown-tOLaD6nm.js} +1 -1
- package/bizar-dash/dist/assets/{markdown-C6mXtQxD.js.map → markdown-tOLaD6nm.js.map} +1 -1
- package/bizar-dash/dist/assets/{mobile-CMHqtLV2.js → mobile-DYCHcUpq.js} +1 -1
- package/bizar-dash/dist/assets/{mobile-CMHqtLV2.js.map → mobile-DYCHcUpq.js.map} +1 -1
- package/bizar-dash/dist/assets/{mobile-layout-3jIhHX_p.js → mobile-layout-CBHjpwsb.js} +2 -2
- package/bizar-dash/dist/assets/{mobile-layout-3jIhHX_p.js.map → mobile-layout-CBHjpwsb.js.map} +1 -1
- package/bizar-dash/dist/assets/{useSlashCommands-DtITw8Xv.js → useSlashCommands-Bd7_FA6U.js} +2 -2
- package/bizar-dash/dist/assets/{useSlashCommands-DtITw8Xv.js.map → useSlashCommands-Bd7_FA6U.js.map} +1 -1
- package/bizar-dash/dist/assets/{vendor-CeHGtduv.js → vendor-C843201K.js} +12 -12
- package/bizar-dash/dist/assets/vendor-C843201K.js.map +1 -0
- package/bizar-dash/dist/index.html +6 -6
- package/bizar-dash/dist/mobile.html +2 -2
- package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/bizar-dash/src/server/api.mjs +4 -4
- package/bizar-dash/src/server/background-store.mjs +15 -16
- package/bizar-dash/src/server/bg-poller.mjs +25 -35
- package/bizar-dash/src/server/bg-retry.mjs +66 -194
- package/bizar-dash/src/server/claude-bg-spawner.mjs +390 -0
- package/bizar-dash/src/server/claude-info.mjs +412 -0
- package/bizar-dash/src/server/{cline-runner.mjs → claude-runner.mjs} +53 -48
- package/bizar-dash/src/server/claude-sdk.mjs +191 -0
- package/bizar-dash/src/server/providers-store.mjs +22 -49
- package/bizar-dash/src/server/routes/background.mjs +24 -20
- package/bizar-dash/src/server/routes/chat.mjs +223 -326
- package/bizar-dash/src/server/routes/claude-session-detail.mjs +329 -0
- package/bizar-dash/src/server/routes/claude-sessions.mjs +259 -0
- package/bizar-dash/src/server/routes/tasks.mjs +20 -28
- package/bizar-dash/src/server/task-delegator.mjs +76 -77
- package/bizar-dash/src/web/components/chat/useChat.ts +23 -27
- package/bizar-dash/src/web/views/Chat.tsx +8 -8
- package/cli/bin.mjs +31 -18
- package/cli/commands/claude-cmd.mjs +348 -0
- package/cli/commands/install.mjs +12 -11
- package/cli/commands/sandbox.mjs +220 -0
- package/cli/commands/validate.mjs +252 -288
- package/cli/dev-link.test.mjs +11 -11
- package/cli/doctor.mjs +131 -213
- package/cli/install.mjs +33 -37
- package/cli/install.test.mjs +9 -9
- package/cli/provision-claude.mjs +893 -0
- package/cli/provision.mjs +330 -226
- package/cli/provision.test.mjs +102 -0
- package/cli/utils.mjs +72 -58
- package/config/AGENTS.md +28 -28
- package/config/agents/_shared/AGENT_BASELINE.md +104 -684
- package/config/skills/bizar/SKILL.md +197 -0
- package/config/skills/cubesandbox/SKILL.md +148 -0
- package/config/skills/harness-engineering/SKILL.md +142 -0
- package/install.sh +66 -44
- package/package.json +19 -11
- package/packages/sdk/ARCHITECTURE.md +40 -36
- package/packages/sdk/package-lock.json +32 -0
- package/packages/sdk/package.json +15 -5
- package/{plugins/bizar → packages/sdk}/src/dangerous-patterns.ts +6 -28
- package/packages/sdk/src/fingerprint.ts +0 -0
- package/packages/sdk/src/index.ts +38 -73
- package/packages/sdk/src/mcp/bin.ts +51 -0
- package/packages/sdk/src/mcp/server.ts +498 -0
- package/{plugins/bizar/src/memory-vault.ts → packages/sdk/src/memory/index.ts} +18 -21
- package/packages/sdk/tests/sdk.test.mjs +148 -0
- package/packages/sdk/vitest.config.ts +1 -1
- package/scripts/bh-full-e2e.mjs +166 -363
- package/scripts/check-deps.mjs +28 -46
- package/scripts/mirror-claude-md.sh +78 -0
- package/scripts/test-in-container.sh +157 -0
- package/templates/clean-state-checklist.md +3 -3
- package/templates/sprint-contract.md +2 -2
- package/bizar-dash/.bizar/activity.log +0 -3
- package/bizar-dash/.omx/logs/omx-2026-07-07.jsonl +0 -1
- package/bizar-dash/.omx/state/session.json +0 -10
- package/bizar-dash/bizar-design/EXPLANATION.md +0 -307
- package/bizar-dash/bizar-design/INSTRUCTIONS.md +0 -149
- package/bizar-dash/bizar-design/canvas.html +0 -281
- package/bizar-dash/bizar-design/canvas.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/components.css +0 -1665
- package/bizar-dash/bizar-design/components.html +0 -557
- package/bizar-dash/bizar-design/components.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/agents.html +0 -74
- package/bizar-dash/bizar-design/desktop/agents.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/memory.html +0 -75
- package/bizar-dash/bizar-design/desktop/memory.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/metrics.html +0 -63
- package/bizar-dash/bizar-design/desktop/metrics.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/overview.html +0 -95
- package/bizar-dash/bizar-design/desktop/overview.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/settings.html +0 -70
- package/bizar-dash/bizar-design/desktop/settings.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/icons.svg +0 -44
- package/bizar-dash/bizar-design/index.html +0 -192
- package/bizar-dash/bizar-design/index.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/agents.html +0 -29
- package/bizar-dash/bizar-design/mobile/agents.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/memory.html +0 -28
- package/bizar-dash/bizar-design/mobile/memory.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/metrics.html +0 -29
- package/bizar-dash/bizar-design/mobile/metrics.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/overview.html +0 -33
- package/bizar-dash/bizar-design/mobile/overview.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/settings.html +0 -28
- package/bizar-dash/bizar-design/mobile/settings.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/prototype.js +0 -114
- package/bizar-dash/bizar-design/tokens.css +0 -106
- package/bizar-dash/dist/assets/vendor-CeHGtduv.js.map +0 -1
- package/bizar-dash/node_modules/.package-lock.json +0 -6
- package/bizar-dash/package-lock.json +0 -6
- package/bizar-dash/src/server/cline-sdk.mjs +0 -132
- package/bizar-dash/src/server/routes/cline-session-detail.mjs +0 -559
- package/bizar-dash/src/server/routes/cline-sessions.mjs +0 -291
- package/cli/commands/cline-cmd.mjs +0 -289
- package/cli/commands/validate.test.mjs +0 -344
- package/cli/doctor.test.mjs +0 -350
- package/config/cline.json.template +0 -342
- package/packages/sdk/src/client.ts +0 -188
- package/packages/sdk/src/cline-events.ts +0 -134
- package/packages/sdk/src/cline-types.ts +0 -66
- package/packages/sdk/src/cline.ts +0 -339
- package/packages/sdk/src/errors.ts +0 -129
- package/packages/sdk/src/events.ts +0 -153
- package/packages/sdk/src/types.ts +0 -176
- package/packages/sdk/tests/client.test.ts +0 -217
- package/packages/sdk/tests/errors.test.ts +0 -108
- package/packages/sdk/tests/events.test.ts +0 -139
- package/packages/sdk/tests/fixtures/fetch-mock.ts +0 -152
- package/packages/sdk/tests/fixtures/sse-mock.ts +0 -30
- package/plugins/bizar/ARCHITECTURE.md +0 -142
- package/plugins/bizar/CONSTRAINTS.md +0 -67
- package/plugins/bizar/LICENSE +0 -21
- package/plugins/bizar/README.md +0 -448
- package/plugins/bizar/index.ts +0 -872
- package/plugins/bizar/package.json +0 -39
- package/plugins/bizar/scripts/check-forbidden-imports.sh +0 -33
- package/plugins/bizar/src/background-state.ts +0 -641
- package/plugins/bizar/src/background.ts +0 -1806
- package/plugins/bizar/src/cline-runner.ts +0 -203
- package/plugins/bizar/src/clineruntime.ts +0 -227
- package/plugins/bizar/src/commands-impl.ts +0 -151
- package/plugins/bizar/src/commands.ts +0 -1799
- package/plugins/bizar/src/compaction.d.mts +0 -48
- package/plugins/bizar/src/compaction.mjs +0 -192
- package/plugins/bizar/src/dashboard-client.ts +0 -233
- package/plugins/bizar/src/event-stream.ts +0 -606
- package/plugins/bizar/src/fingerprint.ts +0 -120
- package/plugins/bizar/src/handoff.ts +0 -79
- package/plugins/bizar/src/hooks/memory-flush-on-compact.ts +0 -123
- package/plugins/bizar/src/hooks/memory-inject.ts +0 -247
- package/plugins/bizar/src/hooks/memory-write-on-end.ts +0 -188
- package/plugins/bizar/src/hooks/skill-curator.ts +0 -180
- package/plugins/bizar/src/http-client.ts +0 -467
- package/plugins/bizar/src/key-rotation.ts +0 -218
- package/plugins/bizar/src/logger.ts +0 -144
- package/plugins/bizar/src/loop-engineering.ts +0 -241
- package/plugins/bizar/src/loop.ts +0 -176
- package/plugins/bizar/src/mistake-recovery.ts +0 -98
- package/plugins/bizar/src/odin.ts +0 -227
- package/plugins/bizar/src/options.ts +0 -470
- package/plugins/bizar/src/plan-fs.ts +0 -323
- package/plugins/bizar/src/reasoning-clean.ts +0 -454
- package/plugins/bizar/src/report.ts +0 -178
- package/plugins/bizar/src/research-prompt.ts +0 -35
- package/plugins/bizar/src/serve-info.ts +0 -228
- package/plugins/bizar/src/serve.ts +0 -496
- package/plugins/bizar/src/settings.ts +0 -349
- package/plugins/bizar/src/state.ts +0 -298
- package/plugins/bizar/src/tool-discipline.ts +0 -105
- package/plugins/bizar/src/tools/agent-browser.ts +0 -315
- package/plugins/bizar/src/tools/bg-collect.ts +0 -131
- package/plugins/bizar/src/tools/bg-get-comments.ts +0 -266
- package/plugins/bizar/src/tools/bg-kill.ts +0 -116
- package/plugins/bizar/src/tools/bg-pause.ts +0 -99
- package/plugins/bizar/src/tools/bg-report-progress.ts +0 -115
- package/plugins/bizar/src/tools/bg-resume.ts +0 -94
- package/plugins/bizar/src/tools/bg-send-message.ts +0 -223
- package/plugins/bizar/src/tools/bg-spawn.ts +0 -502
- package/plugins/bizar/src/tools/bg-status.ts +0 -130
- package/plugins/bizar/src/tools/graph-query.ts +0 -278
- package/plugins/bizar/src/tools/loop-engineering.ts +0 -193
- package/plugins/bizar/src/tools/memory-list.ts +0 -43
- package/plugins/bizar/src/tools/memory-read.ts +0 -69
- package/plugins/bizar/src/tools/memory-search.ts +0 -47
- package/plugins/bizar/src/tools/memory-write.ts +0 -54
- package/plugins/bizar/src/tools/open-kb.ts +0 -198
- package/plugins/bizar/src/tools/plan-action.ts +0 -785
- package/plugins/bizar/src/tools/read-glyph-feedback.ts +0 -191
- package/plugins/bizar/src/tools/team-spawn.ts +0 -73
- package/plugins/bizar/src/tools/team-status.ts +0 -76
- package/plugins/bizar/src/tools/wait-for-feedback.ts +0 -415
- package/plugins/bizar/src/trajectory.ts +0 -104
- package/plugins/bizar/tests/README.md +0 -99
- package/plugins/bizar/tests/attach-handler-bug.test.ts +0 -169
- package/plugins/bizar/tests/background-state.test.ts +0 -277
- package/plugins/bizar/tests/background.test.ts +0 -402
- package/plugins/bizar/tests/block.test.ts +0 -195
- package/plugins/bizar/tests/canonical-key-order.test.ts +0 -75
- package/plugins/bizar/tests/clineruntime-config.test.ts +0 -283
- package/plugins/bizar/tests/commands-impl.test.ts +0 -316
- package/plugins/bizar/tests/commands.test.ts +0 -584
- package/plugins/bizar/tests/compaction.test.ts +0 -264
- package/plugins/bizar/tests/config.test.ts +0 -128
- package/plugins/bizar/tests/dashboard-client.test.ts +0 -159
- package/plugins/bizar/tests/dispose.test.ts +0 -336
- package/plugins/bizar/tests/event-stream.test.ts +0 -409
- package/plugins/bizar/tests/event.test.ts +0 -262
- package/plugins/bizar/tests/fingerprint.test.ts +0 -162
- package/plugins/bizar/tests/http-client.test.ts +0 -404
- package/plugins/bizar/tests/init-helpers.test.ts +0 -203
- package/plugins/bizar/tests/integration/slash-command.test.ts +0 -349
- package/plugins/bizar/tests/integration/tool-routing.test.ts +0 -98
- package/plugins/bizar/tests/key-rotation.test.ts +0 -396
- package/plugins/bizar/tests/loop-engineering.test.ts +0 -168
- package/plugins/bizar/tests/loop.test.ts +0 -397
- package/plugins/bizar/tests/memory-write-on-end.test.ts +0 -92
- package/plugins/bizar/tests/mistake-recovery.test.ts +0 -116
- package/plugins/bizar/tests/odin.test.ts +0 -125
- package/plugins/bizar/tests/options.test.ts +0 -329
- package/plugins/bizar/tests/reasoning-clean.test.ts +0 -422
- package/plugins/bizar/tests/safety.test.ts +0 -256
- package/plugins/bizar/tests/serve.test.ts +0 -339
- package/plugins/bizar/tests/settings.test.ts +0 -351
- package/plugins/bizar/tests/stall-think.test.ts +0 -750
- package/plugins/bizar/tests/state.test.ts +0 -276
- package/plugins/bizar/tests/tool-discipline.test.ts +0 -77
- package/plugins/bizar/tests/tools/agent-browser.test.ts +0 -98
- package/plugins/bizar/tests/tools/bg-collect.test.ts +0 -337
- package/plugins/bizar/tests/tools/bg-get-comments.test.ts +0 -485
- package/plugins/bizar/tests/tools/bg-kill.test.ts +0 -235
- package/plugins/bizar/tests/tools/bg-pause.test.ts +0 -61
- package/plugins/bizar/tests/tools/bg-report-progress.test.ts +0 -79
- package/plugins/bizar/tests/tools/bg-resume.test.ts +0 -40
- package/plugins/bizar/tests/tools/bg-send-message.test.ts +0 -116
- package/plugins/bizar/tests/tools/bg-spawn-delegation.test.ts +0 -147
- package/plugins/bizar/tests/tools/bg-spawn-http.test.ts +0 -233
- package/plugins/bizar/tests/tools/bg-spawn.test.ts +0 -311
- package/plugins/bizar/tests/tools/bg-status.test.ts +0 -217
- package/plugins/bizar/tests/tools/cline-runner.test.ts +0 -115
- package/plugins/bizar/tests/tools/plan-action.test.ts +0 -599
- package/plugins/bizar/tests/tools/read-glyph-feedback.test.ts +0 -253
- package/plugins/bizar/tests/tools/wait-for-feedback.test.ts +0 -390
- package/plugins/bizar/tests/update-deadlock.test.ts +0 -151
- package/plugins/bizar/tsconfig.json +0 -29
package/cli/dev-link.test.mjs
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
* Tests for the `bizar dev-link` / `bizar dev-unlink` subcommands.
|
|
5
5
|
* Uses Node's built-in node:test (no external test framework).
|
|
6
6
|
*
|
|
7
|
-
* Strategy: mock HOME (and XDG_CONFIG_HOME) so
|
|
7
|
+
* Strategy: mock HOME (and XDG_CONFIG_HOME) so claudeConfigDir() in
|
|
8
8
|
* cli/utils.mjs returns a path inside a tmpdir, and exercise the
|
|
9
9
|
* create/remove symlink behavior against a controlled filesystem.
|
|
10
10
|
*
|
|
11
11
|
* Note: We mock HOME *before* importing dev-link.mjs because the module
|
|
12
|
-
* imports
|
|
12
|
+
* imports claudeConfigDir transitively from utils.mjs. The path is
|
|
13
13
|
* resolved at call time, though, so the mock just needs to be in place
|
|
14
14
|
* when the functions run.
|
|
15
15
|
*/
|
|
@@ -40,28 +40,28 @@ const ORIG_HOME = process.env.HOME;
|
|
|
40
40
|
const ORIG_XDG = process.env.XDG_CONFIG_HOME;
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
* Point HOME at a fresh tmpdir so the module's
|
|
44
|
-
* resolves inside it (via the fallback `<HOME>/.
|
|
43
|
+
* Point HOME at a fresh tmpdir so the module's claudeConfigDir()
|
|
44
|
+
* resolves inside it (via the fallback `<HOME>/.claude`).
|
|
45
45
|
* Returns the tmpdir path.
|
|
46
46
|
*
|
|
47
47
|
* Note: we deliberately do NOT set XDG_CONFIG_HOME here. The
|
|
48
|
-
*
|
|
49
|
-
* direct parent (so `XDG_CONFIG_HOME=~/.config` → `~/.
|
|
48
|
+
* claudeConfigDir() helper treats a set XDG_CONFIG_HOME as the
|
|
49
|
+
* direct parent (so `XDG_CONFIG_HOME=~/.config` → `~/.claude`,
|
|
50
50
|
* matching the standard layout). Setting it to a raw tmpdir would
|
|
51
|
-
* produce `<tmpdir>/
|
|
52
|
-
* `<tmpdir>/.
|
|
51
|
+
* produce `<tmpdir>/claude` instead of the expected
|
|
52
|
+
* `<tmpdir>/.claude` and break path alignment with the test.
|
|
53
53
|
*/
|
|
54
54
|
function freshHome() {
|
|
55
55
|
const home = mkdtempSync(join(tmpdir(), 'bizar-devlink-'));
|
|
56
56
|
process.env.HOME = home;
|
|
57
|
-
delete process.env.
|
|
58
|
-
delete process.env.
|
|
57
|
+
delete process.env.CLAUDE_CONFIG_DIR;
|
|
58
|
+
delete process.env.BIZAR_LEGACY_CLAUDE_DIR;
|
|
59
59
|
return home;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/** Path to the deployed plugin dir under the mocked HOME. */
|
|
63
63
|
function pluginDest(home) {
|
|
64
|
-
return join(home, '.
|
|
64
|
+
return join(home, '.claude', 'plugins', 'bizar');
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
after(() => {
|
package/cli/doctor.mjs
CHANGED
|
@@ -1,86 +1,53 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* cli/doctor.mjs
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* v6.3.0 — `bizar doctor` subcommand (Claude Code-native).
|
|
5
5
|
*
|
|
6
|
-
* Runs a battery of health checks against the local Bizar /
|
|
6
|
+
* Runs a battery of health checks against the local Bizar / Claude Code
|
|
7
7
|
* install and reports pass/fail for each. Returns a structured summary
|
|
8
8
|
* suitable for callers (e.g. `bizar update`) that want to act on the
|
|
9
9
|
* result without re-printing the per-check output.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* Checks (9 total):
|
|
12
|
+
* claude-cli-reachable: claude --version exits 0
|
|
13
|
+
* settings-valid: ~/.claude/settings.json parses
|
|
14
|
+
* mcp-server-registered: settings.json has mcpServers.bizar
|
|
15
|
+
* hooks-wired: settings.json has PreToolUse/PostToolUse/etc
|
|
16
|
+
* agent-files-installed: agent .md files deployed
|
|
17
|
+
* skill-files-installed: SKILL.md files deployed
|
|
18
|
+
* tools-on-path: at least one of headroom/semble/skills/claude
|
|
19
|
+
* memory-vault: BIZAR_HOME exists (memory subdir lazy)
|
|
20
|
+
* 9router-reachable: provider gateway responds
|
|
15
21
|
*
|
|
16
22
|
* Usage:
|
|
17
|
-
* import { runDoctor } from
|
|
18
|
-
* const r = await runDoctor();
|
|
19
|
-
* const r = await runDoctor({ silent: true });
|
|
23
|
+
* import { runDoctor } from "./doctor.mjs";
|
|
24
|
+
* const r = await runDoctor();
|
|
25
|
+
* const r = await runDoctor({ silent: true });
|
|
20
26
|
*/
|
|
21
27
|
import chalk from 'chalk';
|
|
22
28
|
import { spawnSync } from 'node:child_process';
|
|
23
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
29
|
+
import { existsSync, readFileSync, statSync, readdirSync } from 'node:fs';
|
|
24
30
|
import { join } from 'node:path';
|
|
25
|
-
import {
|
|
31
|
+
import { homedir } from 'node:os';
|
|
26
32
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// doctor to silently under-count ("all 4 core agents present" when there
|
|
30
|
-
// are actually 14). The list mirrors cli/install.mjs AGENT_FILES plus
|
|
31
|
-
// `agent-browser.md` (added in v3.20.7) and `_shared/AGENT_BASELINE.md`
|
|
32
|
-
// is intentionally excluded (it's a skill, not an agent).
|
|
33
|
-
const REQUIRED_AGENTS = [
|
|
34
|
-
'odin.md',
|
|
35
|
-
'vor.md',
|
|
36
|
-
'frigg.md',
|
|
37
|
-
'quick.md',
|
|
38
|
-
'mimir.md',
|
|
39
|
-
'heimdall.md',
|
|
40
|
-
'hermod.md',
|
|
41
|
-
'thor.md',
|
|
42
|
-
'baldr.md',
|
|
43
|
-
'tyr.md',
|
|
44
|
-
'vidarr.md',
|
|
45
|
-
'forseti.md',
|
|
46
|
-
'semble-search.md',
|
|
47
|
-
'agent-browser.md',
|
|
48
|
-
];
|
|
49
|
-
|
|
50
|
-
// ── helpers ─────────────────────────────────────────────────────────────────
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Run a check function and capture its result. The check either
|
|
54
|
-
* returns a string message (pass) or throws an Error (fail).
|
|
55
|
-
*/
|
|
56
|
-
async function runCheck(name, fn) {
|
|
57
|
-
try {
|
|
58
|
-
const message = await fn();
|
|
59
|
-
return { name, ok: true, message: message || 'ok' };
|
|
60
|
-
} catch (err) {
|
|
61
|
-
return {
|
|
62
|
-
name,
|
|
63
|
-
ok: false,
|
|
64
|
-
message: err && err.message ? err.message : String(err),
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
}
|
|
33
|
+
const CLAUDE_DIR = process.env.CLAUDE_CONFIG_DIR || join(homedir(), '.claude');
|
|
34
|
+
const BIZAR_HOME = process.env.BIZAR_HOME || join(homedir(), '.bizar_home');
|
|
68
35
|
|
|
69
36
|
// ── individual checks ───────────────────────────────────────────────────────
|
|
70
37
|
|
|
71
|
-
async function
|
|
72
|
-
const r = spawnSync('
|
|
38
|
+
async function checkClaudeReachable() {
|
|
39
|
+
const r = spawnSync('claude', ['--version'], {
|
|
73
40
|
encoding: 'utf8',
|
|
74
41
|
timeout: 5000,
|
|
75
42
|
});
|
|
76
43
|
if (r.status !== 0) {
|
|
77
|
-
throw new Error(`
|
|
44
|
+
throw new Error(`claude --version exited ${r.status}`);
|
|
78
45
|
}
|
|
79
|
-
return (r.stdout || r.stderr || '').trim().split('\n')[0] || '
|
|
46
|
+
return (r.stdout || r.stderr || '').trim().split('\n')[0] || 'claude available';
|
|
80
47
|
}
|
|
81
48
|
|
|
82
|
-
async function
|
|
83
|
-
const cfgPath = join(
|
|
49
|
+
async function checkSettingsValid() {
|
|
50
|
+
const cfgPath = join(CLAUDE_DIR, 'settings.json');
|
|
84
51
|
if (!existsSync(cfgPath)) {
|
|
85
52
|
throw new Error(`not found at ${cfgPath}`);
|
|
86
53
|
}
|
|
@@ -89,73 +56,56 @@ async function checkConfigValid() {
|
|
|
89
56
|
} catch (err) {
|
|
90
57
|
throw new Error(`invalid JSON: ${err.message}`);
|
|
91
58
|
}
|
|
92
|
-
return '
|
|
59
|
+
return 'settings.json parses';
|
|
93
60
|
}
|
|
94
61
|
|
|
95
|
-
async function
|
|
96
|
-
const cfgPath = join(
|
|
62
|
+
async function checkMcpServerRegistered() {
|
|
63
|
+
const cfgPath = join(CLAUDE_DIR, 'settings.json');
|
|
97
64
|
const cfg = JSON.parse(readFileSync(cfgPath, 'utf8'));
|
|
98
|
-
const
|
|
99
|
-
if (
|
|
100
|
-
throw new Error('
|
|
65
|
+
const servers = cfg.mcpServers || {};
|
|
66
|
+
if (!servers.bizar) {
|
|
67
|
+
throw new Error('mcpServers.bizar missing from settings.json');
|
|
101
68
|
}
|
|
102
|
-
|
|
103
|
-
if (typeof p === 'string') return p.includes('bizar');
|
|
104
|
-
if (Array.isArray(p)) {
|
|
105
|
-
const [path] = p;
|
|
106
|
-
return typeof path === 'string' && path.includes('bizar');
|
|
107
|
-
}
|
|
108
|
-
if (p && typeof p === 'object') {
|
|
109
|
-
return (
|
|
110
|
-
(p.name || '').includes('bizar') ||
|
|
111
|
-
(p.path || '').includes('bizar')
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
return false;
|
|
115
|
-
});
|
|
116
|
-
if (!hasBizar) {
|
|
117
|
-
throw new Error('bizar not found in plugin[]');
|
|
118
|
-
}
|
|
119
|
-
return 'bizar present in plugin[]';
|
|
69
|
+
return `bizar MCP server registered (${servers.bizar.command ?? '?'})`;
|
|
120
70
|
}
|
|
121
71
|
|
|
122
|
-
async function
|
|
123
|
-
const cfgPath = join(
|
|
72
|
+
async function checkHooksWired() {
|
|
73
|
+
const cfgPath = join(CLAUDE_DIR, 'settings.json');
|
|
124
74
|
const cfg = JSON.parse(readFileSync(cfgPath, 'utf8'));
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const [path] = p;
|
|
131
|
-
if (typeof path === 'string') entryPath = path;
|
|
132
|
-
} else if (p && typeof p === 'object' && p.path) {
|
|
133
|
-
entryPath = p.path;
|
|
134
|
-
}
|
|
135
|
-
if (!entryPath) continue;
|
|
136
|
-
const isAbs = entryPath.startsWith('/') || /^[a-z]:[\\/]/i.test(entryPath);
|
|
137
|
-
const resolved = isAbs ? entryPath : join(clineConfigDir(), entryPath);
|
|
138
|
-
lastChecked = resolved;
|
|
139
|
-
if (!existsSync(resolved)) {
|
|
140
|
-
throw new Error(`plugin path does not exist: ${resolved}`);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
if (lastChecked === null) {
|
|
144
|
-
return 'no plugin path to check';
|
|
75
|
+
const hooks = cfg.hooks || {};
|
|
76
|
+
const required = ['PreToolUse', 'PostToolUse', 'SessionStart', 'UserPromptSubmit'];
|
|
77
|
+
const missing = required.filter((e) => !Array.isArray(hooks[e]) || hooks[e].length === 0);
|
|
78
|
+
if (missing.length > 0) {
|
|
79
|
+
throw new Error(`missing hook events: ${missing.join(', ')}`);
|
|
145
80
|
}
|
|
146
|
-
return `
|
|
81
|
+
return `hooks wired: ${required.join(', ')}`;
|
|
147
82
|
}
|
|
148
83
|
|
|
149
84
|
async function checkAgentFilesInstalled() {
|
|
150
|
-
const dir =
|
|
85
|
+
const dir = join(CLAUDE_DIR, 'agents');
|
|
151
86
|
if (!existsSync(dir)) {
|
|
152
87
|
throw new Error(`agents dir missing: ${dir}`);
|
|
153
88
|
}
|
|
154
|
-
const
|
|
155
|
-
if (
|
|
156
|
-
throw new Error(
|
|
89
|
+
const have = readdirSync(dir).filter((f) => f.endsWith('.md'));
|
|
90
|
+
if (have.length === 0) {
|
|
91
|
+
throw new Error('no agent .md files installed');
|
|
92
|
+
}
|
|
93
|
+
return `${have.length} agents installed: ${have.slice(0, 4).join(', ')}${have.length > 4 ? '…' : ''}`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function checkSkillFilesInstalled() {
|
|
97
|
+
const dir = join(CLAUDE_DIR, 'skills');
|
|
98
|
+
if (!existsSync(dir)) {
|
|
99
|
+
throw new Error(`skills dir missing: ${dir}`);
|
|
100
|
+
}
|
|
101
|
+
const skills = readdirSync(dir).filter((d) => {
|
|
102
|
+
const fp = join(dir, d, 'SKILL.md');
|
|
103
|
+
return existsSync(fp);
|
|
104
|
+
});
|
|
105
|
+
if (skills.length === 0) {
|
|
106
|
+
throw new Error('no SKILL.md files found');
|
|
157
107
|
}
|
|
158
|
-
return
|
|
108
|
+
return `${skills.length} skills installed`;
|
|
159
109
|
}
|
|
160
110
|
|
|
161
111
|
/**
|
|
@@ -165,7 +115,7 @@ async function checkAgentFilesInstalled() {
|
|
|
165
115
|
* overall health report.
|
|
166
116
|
*/
|
|
167
117
|
async function checkToolsAvailable() {
|
|
168
|
-
const tools = ['headroom', 'semble', 'skills'];
|
|
118
|
+
const tools = ['headroom', 'semble', 'skills', 'claude'];
|
|
169
119
|
const found = tools.filter(which);
|
|
170
120
|
if (found.length === 0) {
|
|
171
121
|
throw new Error(`none of ${tools.join('/')} on PATH`);
|
|
@@ -173,127 +123,95 @@ async function checkToolsAvailable() {
|
|
|
173
123
|
return `available: ${found.join(', ')}`;
|
|
174
124
|
}
|
|
175
125
|
|
|
176
|
-
async function
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
throw new Error('cline.json missing');
|
|
126
|
+
async function checkMemoryVault() {
|
|
127
|
+
if (!existsSync(BIZAR_HOME)) {
|
|
128
|
+
throw new Error(`BIZAR_HOME missing: ${BIZAR_HOME}`);
|
|
180
129
|
}
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const nine = cfg.provider && cfg.provider['9router'];
|
|
186
|
-
if (nine && nine.baseUrl) {
|
|
187
|
-
const models = nine.models || {};
|
|
188
|
-
const sane = Object.keys(models).filter((id) => typeof id === 'string' && id.length > 0);
|
|
189
|
-
if (sane.length === 0) {
|
|
190
|
-
throw new Error(
|
|
191
|
-
'provider.9router block has no models (run `bizar update` to re-sync)',
|
|
192
|
-
);
|
|
193
|
-
}
|
|
194
|
-
return `provider.9router baseUrl=${nine.baseUrl} sane (${sane.length} models)`;
|
|
130
|
+
const memDir = process.env.BIZAR_MEMORY_VAULT || join(BIZAR_HOME, 'memory');
|
|
131
|
+
if (!existsSync(memDir)) {
|
|
132
|
+
// Not fatal — the vault is created lazily on first write.
|
|
133
|
+
return `BIZAR_HOME present; memory vault will be created on demand`;
|
|
195
134
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
// older pre-v6.0.1 cline.json installs.
|
|
199
|
-
const minimax = cfg.provider && cfg.provider.minimax;
|
|
200
|
-
if (!minimax) {
|
|
201
|
-
return 'warn: no provider.9router AND no provider.minimax — run `bizar update`';
|
|
202
|
-
}
|
|
203
|
-
const models = minimax.models || {};
|
|
204
|
-
const saneNames = Object.entries(models).filter(([, m]) => {
|
|
205
|
-
return (
|
|
206
|
-
m &&
|
|
207
|
-
typeof m === 'object' &&
|
|
208
|
-
'interleaved' in m &&
|
|
209
|
-
'reasoning' in m
|
|
210
|
-
);
|
|
211
|
-
});
|
|
212
|
-
if (saneNames.length === 0) {
|
|
213
|
-
throw new Error(
|
|
214
|
-
'no MiniMax-style model with interleaved + reasoning flags',
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
return `provider.minimax + ${saneNames.length} model(s) sane (legacy; consider migrating to provider.9router)`;
|
|
135
|
+
const st = statSync(memDir);
|
|
136
|
+
return `memory vault at ${memDir} (${st.isDirectory() ? 'dir' : '?'})`;
|
|
218
137
|
}
|
|
219
138
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
* design — the user might be intentionally working offline — but a
|
|
224
|
-
* loud warning keeps the issue from being silent.
|
|
225
|
-
*/
|
|
226
|
-
async function check9routerReachable() {
|
|
227
|
-
const url = process.env.NINEROUTER_URL || 'http://localhost:20128';
|
|
228
|
-
const ac = new AbortController();
|
|
229
|
-
const timer = setTimeout(() => ac.abort(), 4000);
|
|
139
|
+
async function check9RouterReachable() {
|
|
140
|
+
const url = process.env.NINEROUTER_URL || 'http://127.0.0.1:8787';
|
|
141
|
+
let res;
|
|
230
142
|
try {
|
|
231
|
-
|
|
232
|
-
if (!res.ok) {
|
|
233
|
-
return `warn: 9router at ${url} returned HTTP ${res.status}`;
|
|
234
|
-
}
|
|
235
|
-
const body = await res.text().catch(() => '');
|
|
236
|
-
if (!body.includes('"ok":true')) {
|
|
237
|
-
return `warn: 9router at ${url} responded but body did not include ok:true (got: ${body.slice(0, 60)})`;
|
|
238
|
-
}
|
|
239
|
-
return `9router healthy at ${url}`;
|
|
143
|
+
res = await fetch(`${url}/health`, { signal: AbortSignal.timeout(3000) });
|
|
240
144
|
} catch (err) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
145
|
+
throw new Error(`9router at ${url} unreachable: ${err.message ?? err}`);
|
|
146
|
+
}
|
|
147
|
+
if (!res.ok) {
|
|
148
|
+
throw new Error(`9router at ${url} responded HTTP ${res.status}`);
|
|
245
149
|
}
|
|
150
|
+
return `9router at ${url} ok`;
|
|
246
151
|
}
|
|
247
152
|
|
|
153
|
+
// ── runner ──────────────────────────────────────────────────────────────────
|
|
154
|
+
|
|
248
155
|
const CHECKS = [
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
156
|
+
{ name: 'claude-cli-reachable', run: checkClaudeReachable },
|
|
157
|
+
{ name: 'settings-valid', run: checkSettingsValid },
|
|
158
|
+
{ name: 'mcp-server-registered', run: checkMcpServerRegistered },
|
|
159
|
+
{ name: 'hooks-wired', run: checkHooksWired },
|
|
160
|
+
{ name: 'agent-files-installed', run: checkAgentFilesInstalled },
|
|
161
|
+
{ name: 'skill-files-installed', run: checkSkillFilesInstalled },
|
|
162
|
+
{ name: 'tools-on-path', run: checkToolsAvailable },
|
|
163
|
+
{ name: 'memory-vault', run: checkMemoryVault },
|
|
164
|
+
{ name: '9router-reachable', run: check9RouterReachable },
|
|
257
165
|
];
|
|
258
166
|
|
|
259
|
-
// ── public API ──────────────────────────────────────────────────────────────
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Run all health checks. Prints per-check output unless `opts.silent`.
|
|
263
|
-
* Prints a final summary line unless `opts.json` is true.
|
|
264
|
-
* Returns `{ passed, failed, results }`.
|
|
265
|
-
*/
|
|
266
167
|
export async function runDoctor(opts = {}) {
|
|
267
168
|
const silent = !!opts.silent;
|
|
268
|
-
const jsonMode = !!opts.json;
|
|
269
169
|
const results = [];
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
170
|
+
let passed = 0;
|
|
171
|
+
let failed = 0;
|
|
172
|
+
|
|
173
|
+
for (const check of CHECKS) {
|
|
174
|
+
let result;
|
|
175
|
+
try {
|
|
176
|
+
const message = await check.run();
|
|
177
|
+
result = { name: check.name, ok: true, message: message ?? 'ok' };
|
|
178
|
+
} catch (err) {
|
|
179
|
+
result = { name: check.name, ok: false, message: err?.message ?? String(err) };
|
|
180
|
+
}
|
|
181
|
+
results.push(result);
|
|
182
|
+
if (result.ok) passed += 1;
|
|
183
|
+
else failed += 1;
|
|
184
|
+
|
|
273
185
|
if (!silent) {
|
|
274
|
-
const
|
|
275
|
-
|
|
276
|
-
const msg = r.ok ? chalk.dim(` ${r.message}`) : chalk.red(` ${r.message}`);
|
|
277
|
-
console.log(` ${marker} ${label}${msg}`);
|
|
186
|
+
const tag = result.ok ? chalk.green(' ✔ ') : chalk.red(' ✖ ');
|
|
187
|
+
process.stdout.write(`${tag}${check.name}${result.ok ? '' : ` — ${result.message}`}\n`);
|
|
278
188
|
}
|
|
279
189
|
}
|
|
280
190
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
console.log(
|
|
289
|
-
chalk.green(` ✓ ${passed} checks passed, ${failed} failed`),
|
|
290
|
-
);
|
|
291
|
-
} else {
|
|
292
|
-
console.log(
|
|
293
|
-
chalk.yellow(` ⚠ ${passed} checks passed, ${failed} failed`),
|
|
294
|
-
);
|
|
295
|
-
}
|
|
191
|
+
if (!silent) {
|
|
192
|
+
const summary = chalk.bold(
|
|
193
|
+
failed > 0
|
|
194
|
+
? chalk.red(`${failed} checks failed, ${passed} passed`)
|
|
195
|
+
: chalk.green(`${passed} checks passed`),
|
|
196
|
+
);
|
|
197
|
+
process.stdout.write(`\n${summary}\n`);
|
|
296
198
|
}
|
|
297
199
|
|
|
298
200
|
return { passed, failed, results };
|
|
299
|
-
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// ── helper ──────────────────────────────────────────────────────────────────
|
|
204
|
+
|
|
205
|
+
function which(cmd) {
|
|
206
|
+
const r = spawnSync('which', [cmd], { encoding: 'utf8' });
|
|
207
|
+
return r.status === 0 && !!r.stdout?.trim();
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Stand-alone CLI invocation (so `bizar doctor` still works when imported
|
|
211
|
+
// without the bin dispatcher).
|
|
212
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
213
|
+
const silent = process.argv.includes('--silent');
|
|
214
|
+
runDoctor({ silent }).then(({ failed }) => {
|
|
215
|
+
process.exit(failed === 0 ? 0 : 1);
|
|
216
|
+
});
|
|
217
|
+
}
|
package/cli/install.mjs
CHANGED
|
@@ -16,7 +16,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
16
16
|
|
|
17
17
|
import { showBanner, showPantheon, sectionHeading } from './banner.mjs';
|
|
18
18
|
import { promptComponents, promptInstallMode, promptAgents, promptSkillPacks, promptApiKeys, promptConfirmInstall, promptRestartCline } from './prompts.mjs';
|
|
19
|
-
import {
|
|
19
|
+
import { detectClaude, detectHeadroom, detectSemble, detectSkillsCli, detectUv, buildSummary, claudeAgentsDir, claudeConfigDir, repoPath } from './utils.mjs';
|
|
20
20
|
import { installAgents, installAgentsMd, installSkill, installClineJson, installBizarFolder, installPluginBizar, installHeadroom, installSemble, installSkillsCli, installCuratedSkills, installRules, installHooks, installCommands, installCommandsBizar, mergeToolsIntoUserConfig } from './copy.mjs';
|
|
21
21
|
|
|
22
22
|
const AGENT_FILES = [
|
|
@@ -27,8 +27,12 @@ const AGENT_FILES = [
|
|
|
27
27
|
];
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* Install the Bizar
|
|
31
|
-
*
|
|
30
|
+
* Install the Bizar MCP server from this package's own `plugins/bizar/`
|
|
31
|
+
* directory into `~/.claude/plugins/bizar/`.
|
|
32
|
+
*
|
|
33
|
+
* v6.3.0 — Bizar is Claude Code-native. The plugin entry-point still
|
|
34
|
+
* ships at `plugins/bizar/` as a back-compat shim that re-exports the
|
|
35
|
+
* SDK; the actual MCP server lives in `packages/sdk/src/mcp/bin.ts`.
|
|
32
36
|
*
|
|
33
37
|
* v4.0.0 consolidated everything into one npm package, so the plugin
|
|
34
38
|
* source ships with `@polderlabs/bizar` itself — no separate
|
|
@@ -44,8 +48,8 @@ const AGENT_FILES = [
|
|
|
44
48
|
* workspace-internal package not on the public registry. After copying
|
|
45
49
|
* the plugin files, this function ALSO copies the source's `node_modules/`
|
|
46
50
|
* to the deployed `node_modules/` so Bun can resolve the import when the
|
|
47
|
-
* plugin is loaded from `~/.
|
|
48
|
-
*
|
|
51
|
+
* plugin is loaded from `~/.claude/plugins/bizar/`. Without this, the
|
|
52
|
+
* plugin silently fails to load.
|
|
49
53
|
*
|
|
50
54
|
* Pass `{ silent: true }` to suppress the warning prints; the function
|
|
51
55
|
* still returns `true` if the dest is already in the desired state.
|
|
@@ -65,7 +69,7 @@ export async function installPluginFromGlobal(opts = {}) {
|
|
|
65
69
|
// A plain copy would dereference the symlink and silently break the
|
|
66
70
|
// dev workflow. Print a hint unless silent, or honour an explicit
|
|
67
71
|
// --force from the caller.
|
|
68
|
-
const destDir = join(
|
|
72
|
+
const destDir = join(claudeConfigDir(), 'plugins', 'bizar');
|
|
69
73
|
let destIsSymlink = false;
|
|
70
74
|
try {
|
|
71
75
|
destIsSymlink = lstatSync(destDir).isSymbolicLink();
|
|
@@ -81,7 +85,7 @@ export async function installPluginFromGlobal(opts = {}) {
|
|
|
81
85
|
}
|
|
82
86
|
console.log(
|
|
83
87
|
chalk.yellow(
|
|
84
|
-
' ⚠ ~/.
|
|
88
|
+
' ⚠ ~/.claude/plugins/bizar is a dev symlink — skipping copy.',
|
|
85
89
|
),
|
|
86
90
|
);
|
|
87
91
|
console.log(
|
|
@@ -197,11 +201,11 @@ export async function installPluginFromGlobal(opts = {}) {
|
|
|
197
201
|
}
|
|
198
202
|
}
|
|
199
203
|
|
|
200
|
-
// Wire runtime deps (`zod` plus `@
|
|
201
|
-
//
|
|
204
|
+
// Wire runtime deps (`zod` plus `@anthropic-ai/claude-agent-sdk`)
|
|
205
|
+
// into the deployed plugin's `node_modules/`.
|
|
202
206
|
// Bun's module resolver walks up from the plugin entry point
|
|
203
207
|
// looking for `node_modules/`, and without entries there the
|
|
204
|
-
// plugin throws `Cannot find module 'zod'
|
|
208
|
+
// plugin throws `Cannot find module 'zod'` at startup.
|
|
205
209
|
//
|
|
206
210
|
// The resolution logic lives in `cli/plugin-runtime-deps.mjs` and
|
|
207
211
|
// is shared with the modern provisioner (`cli/provision.mjs`). It
|
|
@@ -479,46 +483,38 @@ async function promptGraphifyInstall() {
|
|
|
479
483
|
}
|
|
480
484
|
|
|
481
485
|
export async function runPostInstall() {
|
|
482
|
-
// v6.
|
|
483
|
-
//
|
|
484
|
-
// has been removed; `cli/provision.mjs:runProvision` covers the same
|
|
485
|
-
// surface via `runProvision({ mode: 'install' })`, which is the path
|
|
486
|
+
// v6.3.0 — Bizar is Claude Code-native. `cli/provision-claude.mjs:runProvision`
|
|
487
|
+
// covers the install/update/validate surface and is the primary path
|
|
486
488
|
// used by `bizar install` and `bizar update`. This `runPostInstall`
|
|
487
|
-
// is
|
|
488
|
-
// - copies `config/
|
|
489
|
-
// -
|
|
490
|
-
// - installs agents into `~/.cline/agents/`
|
|
489
|
+
// is a thin Claude Code-native bootstrap that:
|
|
490
|
+
// - copies `config/settings.json` template on first install
|
|
491
|
+
// - installs agents into `~/.claude/agents/`
|
|
491
492
|
// - probes for headroom / semble / skills-cli
|
|
492
493
|
// - installs Headroom via pip or npm
|
|
493
|
-
// The old OpenCode-era probes (`Plugin source present`,
|
|
494
|
-
// `Dashboard source present`) moved to `cli/doctor.mjs` as live checks.
|
|
495
494
|
const { mkdirSync, copyFileSync, existsSync } = await import('node:fs');
|
|
496
495
|
const { execSync } = await import('node:child_process');
|
|
497
496
|
|
|
498
|
-
const dest = join(
|
|
499
|
-
const templateSrc = repoPath('config', '
|
|
497
|
+
const dest = join(claudeConfigDir(), 'settings.json');
|
|
498
|
+
const templateSrc = repoPath('config', 'settings.json');
|
|
500
499
|
if (!existsSync(dest)) {
|
|
501
500
|
if (existsSync(templateSrc)) {
|
|
502
|
-
mkdirSync(
|
|
501
|
+
mkdirSync(claudeConfigDir(), { recursive: true });
|
|
503
502
|
copyFileSync(templateSrc, dest);
|
|
504
|
-
console.log(' ✓
|
|
503
|
+
console.log(' ✓ settings.json bootstrapped from package template');
|
|
505
504
|
}
|
|
506
505
|
}
|
|
507
506
|
|
|
508
|
-
|
|
509
|
-
await installCommandsBizar();
|
|
510
|
-
|
|
511
|
-
const env = await detectCline();
|
|
507
|
+
const env = await detectClaude();
|
|
512
508
|
if (!env.exists) {
|
|
513
|
-
mkdirSync(
|
|
514
|
-
console.log(`BizarHarness: created ${
|
|
509
|
+
mkdirSync(claudeConfigDir(), { recursive: true });
|
|
510
|
+
console.log(`BizarHarness: created ${claudeConfigDir()}/`);
|
|
515
511
|
}
|
|
516
512
|
|
|
517
|
-
mkdirSync(
|
|
513
|
+
mkdirSync(claudeAgentsDir(), { recursive: true });
|
|
518
514
|
|
|
519
515
|
for (const file of AGENT_FILES) {
|
|
520
516
|
const src = repoPath('config', 'agents', file);
|
|
521
|
-
const dest = join(
|
|
517
|
+
const dest = join(claudeAgentsDir(), file);
|
|
522
518
|
if (!existsSync(dest)) {
|
|
523
519
|
copyFileSync(src, dest);
|
|
524
520
|
}
|
|
@@ -537,14 +533,14 @@ export async function runPostInstall() {
|
|
|
537
533
|
'pip install --user "headroom-ai[all]"',
|
|
538
534
|
{ stdio: 'pipe', timeout: 60000 },
|
|
539
535
|
);
|
|
540
|
-
execSync('headroom wrap
|
|
536
|
+
execSync('headroom wrap claude', { stdio: 'pipe' });
|
|
541
537
|
console.log('BizarHarness: Headroom installed and configured.');
|
|
542
538
|
}
|
|
543
539
|
} catch {
|
|
544
540
|
// Fall back to npm
|
|
545
541
|
try {
|
|
546
542
|
execSync('npm install -g headroom-ai', { stdio: 'pipe', timeout: 60000 });
|
|
547
|
-
execSync('headroom wrap
|
|
543
|
+
execSync('headroom wrap claude', { stdio: 'pipe' });
|
|
548
544
|
console.log('BizarHarness: Headroom installed (npm) and configured.');
|
|
549
545
|
} catch {
|
|
550
546
|
console.log('BizarHarness: Headroom install failed. Install manually: pip install "headroom-ai[all]" or npm install -g headroom-ai');
|
|
@@ -552,10 +548,10 @@ export async function runPostInstall() {
|
|
|
552
548
|
}
|
|
553
549
|
} else {
|
|
554
550
|
try {
|
|
555
|
-
execSync('headroom wrap
|
|
556
|
-
console.log('BizarHarness: Headroom configured for
|
|
551
|
+
execSync('headroom wrap claude', { stdio: 'pipe' });
|
|
552
|
+
console.log('BizarHarness: Headroom configured for claude.');
|
|
557
553
|
} catch {
|
|
558
|
-
console.log('BizarHarness: could not configure Headroom. Run `headroom wrap
|
|
554
|
+
console.log('BizarHarness: could not configure Headroom. Run `headroom wrap claude` manually.');
|
|
559
555
|
}
|
|
560
556
|
}
|
|
561
557
|
|