@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
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Toggle the Bizar visual plan canvas or check its current status.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# /visual-plan — Toggle Visual Plan Canvas
|
|
6
|
+
|
|
7
|
+
Toggle the Bizar visual plan canvas or check its current status.
|
|
8
|
+
|
|
9
|
+
The full arguments are available as `$ARGUMENTS` (and `$1`).
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
/visual-plan on — Enable the visual plan canvas in the current session
|
|
15
|
+
/visual-plan off — Disable the visual plan canvas
|
|
16
|
+
/visual-plan status — Show whether the canvas is currently enabled
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Notes
|
|
20
|
+
|
|
21
|
+
The visual plan canvas shows plans as interactive node graphs. When enabled, plan elements appear as draggable nodes on a canvas that agents can manipulate directly. This is useful for visual thinkers or when planning complex multi-step work.
|
|
22
|
+
|
|
23
|
+
This is a session-level toggle — it affects the current Claude Code
|
|
24
|
+
session only.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Bizar Harness — Claude Code Hooks
|
|
2
|
+
|
|
3
|
+
This directory contains the **Claude Code** adapter scripts that back the
|
|
4
|
+
project-scoped hooks defined in `.claude/settings.json`.
|
|
5
|
+
|
|
6
|
+
They replaced the legacy Cline hooks in `config/hooks/*` (PreToolUse,
|
|
7
|
+
PostToolUse, TaskStart, TaskResume, UserPromptSubmit). The Claude Code
|
|
8
|
+
set is the only supported path on Bizar v6.3.0+; the legacy Cline hooks
|
|
9
|
+
are no longer installed.
|
|
10
|
+
|
|
11
|
+
## Adapter inventory
|
|
12
|
+
|
|
13
|
+
| File | Event | Matcher | Behaviour |
|
|
14
|
+
|------|-------|---------|-----------|
|
|
15
|
+
| `pretooluse-editwrite.mjs` | `PreToolUse` | `Write\|Edit\|MultiEdit\|Bash` | Blocks `.env`/secrets/lockfiles; warns on `console.log`/`debugger`/`.only()` in `src/`; scans `Bash` against the 36-pattern dangerous-pattern list |
|
|
16
|
+
| `posttooluse-editwrite.mjs` | `PostToolUse` | `Edit\|Write\|MultiEdit` | Logs edit/write latency + size to `~/.config/bizar/hook-logs/` |
|
|
17
|
+
| `sessionstart-prime.mjs` | `SessionStart` | (none — branches on `source`) | Primes the agent with CLAUDE.md, AGENTS.md, feature_list state |
|
|
18
|
+
| `userpromptsubmit-tag.mjs` | `UserPromptSubmit` | (none) | Tags prompt for `/team`, `/plow-through`, `/test`, `/validate`, `/plan`, `/audit`, `/pr-review` |
|
|
19
|
+
| `sessionend-recall.mjs` | `SessionEnd` | (none) | Records a session summary to the memory vault at `~/.bizar_home/memory/projects/<name>/sessions/` |
|
|
20
|
+
|
|
21
|
+
## I/O contract
|
|
22
|
+
|
|
23
|
+
Claude Code invokes each hook as a child process, pipes JSON on
|
|
24
|
+
**stdin**, and reads JSON on **stdout**. The five adapters above all
|
|
25
|
+
read using `process.stdin` and write a single JSON object to
|
|
26
|
+
`process.stdout`.
|
|
27
|
+
|
|
28
|
+
### Stdin (varies by event)
|
|
29
|
+
|
|
30
|
+
```jsonc
|
|
31
|
+
// PreToolUse
|
|
32
|
+
{
|
|
33
|
+
"session_id": "...",
|
|
34
|
+
"transcript_path": "...",
|
|
35
|
+
"cwd": "/home/drb0rk/Projects/BizarHarness",
|
|
36
|
+
"hook_event_name": "PreToolUse",
|
|
37
|
+
"tool_name": "Write",
|
|
38
|
+
"tool_input": { "file_path": "/path", "content": "..." }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// PostToolUse (adds tool_response)
|
|
42
|
+
// UserPromptSubmit (uses .user_prompt instead of .tool_name/.tool_input)
|
|
43
|
+
// SessionStart (uses .source = "startup" | "resume" | "clear")
|
|
44
|
+
// SessionEnd (uses .reason = "exit" | "clear" | "logout" | "prompt_input_exit")
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Stdout
|
|
48
|
+
|
|
49
|
+
```jsonc
|
|
50
|
+
// Block (PreToolUse only)
|
|
51
|
+
{
|
|
52
|
+
"hookSpecificOutput": {
|
|
53
|
+
"hookEventName": "PreToolUse",
|
|
54
|
+
"permissionDecision": "deny",
|
|
55
|
+
"permissionDecisionReason": "..."
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Inject context for the next turn (all events)
|
|
60
|
+
{
|
|
61
|
+
"hookSpecificOutput": {
|
|
62
|
+
"hookEventName": "PostToolUse", // or PreToolUse / SessionStart / UserPromptSubmit
|
|
63
|
+
"additionalContext": "..."
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
For a non-blocking `PreToolUse`, omitting `permissionDecision` and
|
|
69
|
+
emitting only `additionalContext` is a soft hint to the model — the
|
|
70
|
+
tool call still proceeds.
|
|
71
|
+
|
|
72
|
+
## Claude Code lifecycle mapping
|
|
73
|
+
|
|
74
|
+
The legacy Cline plugin used four separate events (PreToolUse,
|
|
75
|
+
PostToolUse, TaskStart, TaskResume, UserPromptSubmit). Claude Code
|
|
76
|
+
collapses "task start" and "task resume" into a single `SessionStart`
|
|
77
|
+
event that branches on `source` (`startup`, `resume`, `clear`). The
|
|
78
|
+
adapter `sessionstart-prime.mjs` reads `source` and applies the
|
|
79
|
+
appropriate priming logic for each branch.
|
|
80
|
+
|
|
81
|
+
## Disabling an individual hook
|
|
82
|
+
|
|
83
|
+
Easiest path: comment out the matching `hooks` array entry in
|
|
84
|
+
`.claude/settings.json`. Removing the executable bit
|
|
85
|
+
(`chmod -x …`) also works — Claude Code silently skips hooks it can't
|
|
86
|
+
execute.
|
|
87
|
+
|
|
88
|
+
## See also
|
|
89
|
+
|
|
90
|
+
- `cli/provision-claude.mjs` — installs Claude Code hooks to
|
|
91
|
+
`~/.claude/hooks/` and wires them via `~/.claude/settings.json`.
|
|
92
|
+
- `.claude/settings.json` — the project hook wiring
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// PostToolUse — Bizar harness hook (Claude Code format).
|
|
3
|
+
//
|
|
4
|
+
// Runs AFTER a tool call against `Edit`, `Write`, or `MultiEdit`
|
|
5
|
+
// completes. Logs the edit/write to `~/.config/bizar/hook-logs/` so
|
|
6
|
+
// downstream observability tooling can aggregate latency + size.
|
|
7
|
+
//
|
|
8
|
+
// Claude Code stdin shape:
|
|
9
|
+
// {
|
|
10
|
+
// "session_id": "...",
|
|
11
|
+
// "transcript_path": "...",
|
|
12
|
+
// "cwd": "...",
|
|
13
|
+
// "hook_event_name": "PostToolUse",
|
|
14
|
+
// "tool_name": "Edit",
|
|
15
|
+
// "tool_input": { "file_path": "..." },
|
|
16
|
+
// "tool_response": { ... }
|
|
17
|
+
// }
|
|
18
|
+
//
|
|
19
|
+
// Claude Code stdout shape:
|
|
20
|
+
// { "hookSpecificOutput": {
|
|
21
|
+
// "hookEventName": "PostToolUse",
|
|
22
|
+
// "additionalContext": "note for the next turn"
|
|
23
|
+
// }}
|
|
24
|
+
//
|
|
25
|
+
// Behaviour:
|
|
26
|
+
// 1. Append-only JSONL log under ~/.config/bizar/hook-logs/.
|
|
27
|
+
// 2. Remind to run /test after edits to src/ files.
|
|
28
|
+
|
|
29
|
+
'use strict';
|
|
30
|
+
|
|
31
|
+
import fs from 'node:fs';
|
|
32
|
+
import os from 'node:os';
|
|
33
|
+
import path from 'node:path';
|
|
34
|
+
|
|
35
|
+
let raw = '';
|
|
36
|
+
process.stdin.setEncoding('utf8');
|
|
37
|
+
process.stdin.on('data', (chunk) => { raw += chunk; });
|
|
38
|
+
process.stdin.on('end', () => {
|
|
39
|
+
let input = {};
|
|
40
|
+
try { input = JSON.parse(raw || '{}'); } catch { input = {}; }
|
|
41
|
+
|
|
42
|
+
const toolName = String(input.tool_name || '');
|
|
43
|
+
const toolInput =
|
|
44
|
+
(input.tool_input && typeof input.tool_input === 'object') ? input.tool_input : {};
|
|
45
|
+
const filePath = String(toolInput.file_path || '');
|
|
46
|
+
const sessionId = String(input.session_id || '');
|
|
47
|
+
|
|
48
|
+
// 1. Append-only JSONL log under ~/.config/bizar/hook-logs/.
|
|
49
|
+
try {
|
|
50
|
+
const logDir = path.join(os.homedir(), '.config', 'bizar', 'hook-logs');
|
|
51
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
52
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
53
|
+
const logFile = path.join(logDir, `post-tool-use-${today}.jsonl`);
|
|
54
|
+
const line = JSON.stringify({
|
|
55
|
+
ts: new Date().toISOString(),
|
|
56
|
+
tool: toolName,
|
|
57
|
+
success: true, // PostToolUse only fires on success in Claude Code
|
|
58
|
+
executionTimeMs: 0, // not exposed in Claude Code hook input
|
|
59
|
+
sessionId: sessionId || null,
|
|
60
|
+
});
|
|
61
|
+
fs.appendFileSync(logFile, line + '\n');
|
|
62
|
+
} catch { /* best-effort */ }
|
|
63
|
+
|
|
64
|
+
const notes = [];
|
|
65
|
+
|
|
66
|
+
// 2. Skip the slow-tool warning — Claude Code doesn't surface tool
|
|
67
|
+
// latency in hook input, so no signal to warn on.
|
|
68
|
+
//
|
|
69
|
+
// 3. Surface a reminder for Write/Edit/MultiEdit on src/ paths.
|
|
70
|
+
if (
|
|
71
|
+
/^(write|edit|multiedit)$/i.test(toolName) &&
|
|
72
|
+
/\/(src|plugins|packages)\//.test(filePath.toLowerCase())
|
|
73
|
+
) {
|
|
74
|
+
notes.push(
|
|
75
|
+
"Bizar PostToolUse: if you're done editing, run `/test` to gate the change with tests before claiming complete.",
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (notes.length === 0) {
|
|
80
|
+
process.stdout.write('{}\n');
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const out = {
|
|
85
|
+
hookSpecificOutput: {
|
|
86
|
+
hookEventName: 'PostToolUse',
|
|
87
|
+
additionalContext: notes.join(' '),
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
process.stdout.write(JSON.stringify(out) + '\n');
|
|
91
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* pretooluse-bash.mjs — Claude Code PreToolUse hook (matcher: Bash).
|
|
4
|
+
*
|
|
5
|
+
* Runs the Bizar dangerous-pattern scanner on Bash commands before they
|
|
6
|
+
* execute. Blocks destructive patterns (rm -rf, sudo, SSRF, etc.) via
|
|
7
|
+
* the 36-pattern DANGEROUS_PATTERNS regex list maintained in
|
|
8
|
+
* `@polderlabs/bizar-sdk/dist/dangerous-patterns.js`.
|
|
9
|
+
*
|
|
10
|
+
* Claude Code PreToolUse input schema:
|
|
11
|
+
* { session_id, cwd, hook_event_name: "PreToolUse", tool_name: "Bash", tool_input: { command, description } }
|
|
12
|
+
*
|
|
13
|
+
* Claude Code PreToolUse output schema:
|
|
14
|
+
* { hookSpecificOutput: { hookEventName, permissionDecision, permissionDecisionReason }, additionalContext? }
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
'use strict';
|
|
18
|
+
|
|
19
|
+
let raw = '';
|
|
20
|
+
process.stdin.setEncoding('utf8');
|
|
21
|
+
process.stdin.on('data', (chunk) => { raw += chunk; });
|
|
22
|
+
process.stdin.on('end', () => {
|
|
23
|
+
let input = {};
|
|
24
|
+
try { input = JSON.parse(raw); } catch { input = {}; }
|
|
25
|
+
const toolInput = (input.tool_input && typeof input.tool_input === 'object') ? input.tool_input : {};
|
|
26
|
+
const command = String(toolInput.command || '');
|
|
27
|
+
|
|
28
|
+
// Inline dangerous-pattern scanner. Mirrors
|
|
29
|
+
// `packages/sdk/src/dangerous-patterns.ts` — kept inline so this hook
|
|
30
|
+
// works without importing the SDK at runtime.
|
|
31
|
+
const DANGEROUS = [
|
|
32
|
+
{ name: 'rm-rf-root', pattern: /\brm\s+(-\w*r\w*f\w*\s+)*\/\s*$/i, decision: 'deny', reason: 'Recursive delete of root filesystem' },
|
|
33
|
+
{ name: 'rm-rf-etc', pattern: /\brm\s+(-\w*r\w*f\w*\s+)*\/(etc|var|usr|boot|home)\b/i, decision: 'deny', reason: 'Recursive delete of system directory' },
|
|
34
|
+
{ name: 'rm-rf-wildcard', pattern: /\brm\s+-\w*r\w*f\w*\s+\*/i, decision: 'ask', reason: 'Recursive delete with wildcard' },
|
|
35
|
+
{ name: 'rm-rf-home', pattern: /\brm\s+(-\w*r\w*f\w*\s+)*~?\//i, decision: 'ask', reason: 'Recursive delete of home directory' },
|
|
36
|
+
{ name: 'mkfs', pattern: /\bmkfs(\.\w+)?\s+\/dev\//i, decision: 'deny', reason: 'Format filesystem' },
|
|
37
|
+
{ name: 'dd-of-dev', pattern: /\bdd\s+.*of=\/dev\//i, decision: 'deny', reason: 'dd to raw device' },
|
|
38
|
+
{ name: 'sudo', pattern: /(^|\s|;|&&|\|\|)sudo\b/i, decision: 'ask', reason: 'Sudo escalation' },
|
|
39
|
+
{ name: 'su-root', pattern: /\bsu\s+-?\s*root\b/i, decision: 'ask', reason: 'su to root' },
|
|
40
|
+
{ name: 'curl-metadata', pattern: /169\.254\.169\.254/i, decision: 'deny', reason: 'AWS metadata IP' },
|
|
41
|
+
{ name: 'curl-google-metadata', pattern: /metadata\.google\.internal/i, decision: 'deny', reason: 'GCP metadata hostname' },
|
|
42
|
+
{ name: 'curl-azure-metadata', pattern: /metadata\.azure\.com/i, decision: 'deny', reason: 'Azure metadata hostname' },
|
|
43
|
+
{ name: 'nc-backdoor', pattern: /\bnc\s+(-[a-z]*\s+)*-[a-z]*e\b/i, decision: 'deny', reason: 'nc execute backdoor' },
|
|
44
|
+
{ name: 'wget-pipe-shell', pattern: /\bwget\s+.*\|\s*(ba)?sh\b/i, decision: 'deny', reason: 'wget piped to shell' },
|
|
45
|
+
{ name: 'curl-pipe-shell', pattern: /\bcurl\s+.*\|\s*(ba)?sh\b/i, decision: 'deny', reason: 'curl piped to shell' },
|
|
46
|
+
{ name: 'kill-init', pattern: /\bkill\s+(-9\s+)?1\b/i, decision: 'deny', reason: 'Kill PID 1 (init)' },
|
|
47
|
+
{ name: 'shutdown', pattern: /\b(shutdown|halt|poweroff|reboot)\b/i, decision: 'deny', reason: 'System shutdown' },
|
|
48
|
+
{ name: 'xmrig', pattern: /\b(xmrig|minerd|cpuminer|cgminer)\b/i, decision: 'deny', reason: 'Crypto miner' },
|
|
49
|
+
{ name: 'read-shadow', pattern: /\/etc\/(shadow|passwd|sudoers)\b/i, decision: 'ask', reason: 'Read sensitive system file' },
|
|
50
|
+
{ name: 'read-ssh', pattern: /\.ssh\//i, decision: 'deny', reason: 'Read SSH keys' },
|
|
51
|
+
{ name: 'read-aws-creds', pattern: /~\/\.aws\/credentials/i, decision: 'deny', reason: 'Read AWS credentials' },
|
|
52
|
+
{ name: 'path-traversal', pattern: /(\.\.\/){2,}/i, decision: 'ask', reason: 'Multiple path traversal' },
|
|
53
|
+
{ name: 'git-force-push-main', pattern: /\bgit\s+push\s+(-f|--force)(\s+--.*)?\s+origin\s+(main|master)\b/i, decision: 'deny', reason: 'Force push to main/master' },
|
|
54
|
+
{ name: 'git-reset-hard', pattern: /\bgit\s+reset\s+--hard\b/i, decision: 'ask', reason: 'git reset --hard' },
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
for (const p of DANGEROUS) {
|
|
58
|
+
if (p.pattern.test(command)) {
|
|
59
|
+
const decision = p.decision === 'deny' ? 'deny' : 'ask';
|
|
60
|
+
const out = {
|
|
61
|
+
hookSpecificOutput: {
|
|
62
|
+
hookEventName: 'PreToolUse',
|
|
63
|
+
permissionDecision: decision,
|
|
64
|
+
permissionDecisionReason: `dangerous_pattern:${p.name}: ${p.reason}`,
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
process.stdout.write(JSON.stringify(out) + '\n');
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// No dangerous pattern — allow.
|
|
73
|
+
const out = {
|
|
74
|
+
hookSpecificOutput: {
|
|
75
|
+
hookEventName: 'PreToolUse',
|
|
76
|
+
permissionDecision: 'allow',
|
|
77
|
+
},
|
|
78
|
+
additionalContext: `Bizar PreToolUse(Bash): scanned ${command.length} chars, no dangerous pattern.`,
|
|
79
|
+
};
|
|
80
|
+
process.stdout.write(JSON.stringify(out) + '\n');
|
|
81
|
+
});
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// PreToolUse — Bizar harness hook (Claude Code format).
|
|
3
|
+
//
|
|
4
|
+
// Runs BEFORE any tool call against `Write`, `Edit`, `MultiEdit`, or `Bash`.
|
|
5
|
+
//
|
|
6
|
+
// Claude Code stdin shape:
|
|
7
|
+
// {
|
|
8
|
+
// "session_id": "...",
|
|
9
|
+
// "transcript_path": "...",
|
|
10
|
+
// "cwd": "...",
|
|
11
|
+
// "hook_event_name": "PreToolUse",
|
|
12
|
+
// "tool_name": "Write",
|
|
13
|
+
// "tool_input": { "file_path": "...", "content": "..." }
|
|
14
|
+
// }
|
|
15
|
+
//
|
|
16
|
+
// Claude Code stdout shape:
|
|
17
|
+
// { "hookSpecificOutput": {
|
|
18
|
+
// "hookEventName": "PreToolUse",
|
|
19
|
+
// "permissionDecision": "deny",
|
|
20
|
+
// "permissionDecisionReason": "..."
|
|
21
|
+
// }}
|
|
22
|
+
// ── or ──
|
|
23
|
+
// { "hookSpecificOutput": {
|
|
24
|
+
// "hookEventName": "PreToolUse",
|
|
25
|
+
// "additionalContext": "note for the model"
|
|
26
|
+
// }}
|
|
27
|
+
//
|
|
28
|
+
// Behaviour:
|
|
29
|
+
// 1. Block writes to .env, .envrc, secrets/, credentials/,
|
|
30
|
+
// node_modules/, *.lock, *.lockb, package-lock.json, bun.lock*, yarn.lock.
|
|
31
|
+
// 2. Warn (don't block) on console.log / debugger / .only() in src/.
|
|
32
|
+
// 3. Scan `Bash` commands against the dangerous-patterns list.
|
|
33
|
+
// 4. Always return a small context line for the next AI decision.
|
|
34
|
+
|
|
35
|
+
'use strict';
|
|
36
|
+
|
|
37
|
+
let raw = '';
|
|
38
|
+
process.stdin.setEncoding('utf8');
|
|
39
|
+
process.stdin.on('data', (chunk) => { raw += chunk; });
|
|
40
|
+
process.stdin.on('end', () => {
|
|
41
|
+
let input = {};
|
|
42
|
+
try { input = JSON.parse(raw || '{}'); } catch { input = {}; }
|
|
43
|
+
|
|
44
|
+
const toolName = String(input.tool_name || '');
|
|
45
|
+
const toolInput =
|
|
46
|
+
(input.tool_input && typeof input.tool_input === 'object') ? input.tool_input : {};
|
|
47
|
+
|
|
48
|
+
// Extract the "path" and "content" mapped onto Claude Code's
|
|
49
|
+
// Write/Edit/MultiEdit/Bash shapes.
|
|
50
|
+
let filePath = '';
|
|
51
|
+
let content = '';
|
|
52
|
+
if (toolName === 'Write') {
|
|
53
|
+
filePath = String(toolInput.file_path || '');
|
|
54
|
+
content = String(toolInput.content || '');
|
|
55
|
+
} else if (toolName === 'Edit') {
|
|
56
|
+
filePath = String(toolInput.file_path || '');
|
|
57
|
+
content = String(toolInput.new_string || '');
|
|
58
|
+
} else if (toolName === 'MultiEdit') {
|
|
59
|
+
filePath = String(toolInput.file_path || '');
|
|
60
|
+
const edits = Array.isArray(toolInput.edits) ? toolInput.edits : [];
|
|
61
|
+
content = edits.map((e) => String((e && e.new_string) || '')).join('\n');
|
|
62
|
+
} else if (toolName === 'Bash') {
|
|
63
|
+
// No "path" for Bash — use the command string as the inspect surface.
|
|
64
|
+
content = String(toolInput.command || '');
|
|
65
|
+
} else {
|
|
66
|
+
process.stdout.write('{}\n');
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const lowerPath = filePath.toLowerCase();
|
|
71
|
+
const lowerContent = content.toLowerCase();
|
|
72
|
+
|
|
73
|
+
// 1. Hard block — secrets + protected paths.
|
|
74
|
+
const blocked = [
|
|
75
|
+
/\/\.env(\.|$|\/)/,
|
|
76
|
+
/\/\.envrc$/,
|
|
77
|
+
/\/secrets?\//,
|
|
78
|
+
/\/credentials?/,
|
|
79
|
+
/\/node_modules\//,
|
|
80
|
+
/\.(lock|lockb)$/,
|
|
81
|
+
/\/package-lock\.json$/,
|
|
82
|
+
/\/bun\.lockb?$/,
|
|
83
|
+
/\/yarn\.lock$/,
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
let blockReason = '';
|
|
87
|
+
if (filePath && blocked.some((re) => re.test(lowerPath))) {
|
|
88
|
+
blockReason = filePath;
|
|
89
|
+
} else if (toolName === 'Bash' && blocked.some((re) => re.test(lowerContent))) {
|
|
90
|
+
blockReason = '(matched in Bash command)';
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (blockReason) {
|
|
94
|
+
const out = {
|
|
95
|
+
hookSpecificOutput: {
|
|
96
|
+
hookEventName: 'PreToolUse',
|
|
97
|
+
permissionDecision: 'deny',
|
|
98
|
+
permissionDecisionReason:
|
|
99
|
+
`Bizar PreToolUse: refusing to write to protected path '${blockReason}' (Bizar harness policy).`,
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
process.stdout.write(JSON.stringify(out) + '\n');
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 2. Warn — debug artifacts in src/ (only when a path-shaped target exists).
|
|
107
|
+
const notes = [];
|
|
108
|
+
const target = filePath || content; // for Bash, content == command (rarely matches)
|
|
109
|
+
const lowerTarget = target.toLowerCase();
|
|
110
|
+
if (
|
|
111
|
+
filePath &&
|
|
112
|
+
/\.(ts|tsx|js|jsx|mjs|cjs)$/.test(lowerTarget) &&
|
|
113
|
+
/\/(src|plugins|packages)\//.test(lowerTarget)
|
|
114
|
+
) {
|
|
115
|
+
if (
|
|
116
|
+
/\bconsole\.(log|debug|warn)\b/.test(lowerContent) &&
|
|
117
|
+
!/\bconsole\.(error|info)\b/.test(lowerContent)
|
|
118
|
+
) {
|
|
119
|
+
notes.push("Heads up: console.log detected in src — `make clean-check` will fail.");
|
|
120
|
+
}
|
|
121
|
+
if (/\bdebugger\b/.test(lowerContent)) {
|
|
122
|
+
notes.push('Heads up: debugger statement detected — remove before committing.');
|
|
123
|
+
}
|
|
124
|
+
if (/\.only\s*\(/.test(content) && !/\.skip\s*\(/.test(content)) {
|
|
125
|
+
notes.push("Heads up: .only() detected — `make clean-check` will fail.");
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// 3. Always add a small context line for the AI's next decision.
|
|
130
|
+
notes.push(`Bizar PreToolUse: tool=${toolName || 'unknown'} path=${filePath || '(no path)'}`);
|
|
131
|
+
|
|
132
|
+
const out = {
|
|
133
|
+
hookSpecificOutput: {
|
|
134
|
+
hookEventName: 'PreToolUse',
|
|
135
|
+
additionalContext: notes.join(' '),
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
process.stdout.write(JSON.stringify(out) + '\n');
|
|
139
|
+
});
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* sessionend-recall.mjs — Claude Code SessionEnd hook.
|
|
4
|
+
*
|
|
5
|
+
* Records session summaries to the memory vault and writes a
|
|
6
|
+
* `sessions/<date>-<session-id>.md` note via the in-process vault.
|
|
7
|
+
*
|
|
8
|
+
* Claude Code SessionEnd input schema:
|
|
9
|
+
* { session_id, cwd, hook_event_name: "SessionEnd", reason?: string }
|
|
10
|
+
*
|
|
11
|
+
* Claude Code SessionEnd output schema:
|
|
12
|
+
* { continue?: boolean, stopReason?: string }
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const fs = require('fs');
|
|
18
|
+
const os = require('os');
|
|
19
|
+
const path = require('path');
|
|
20
|
+
|
|
21
|
+
let raw = '';
|
|
22
|
+
process.stdin.setEncoding('utf8');
|
|
23
|
+
process.stdin.on('data', (chunk) => { raw += chunk; });
|
|
24
|
+
process.stdin.on('end', () => {
|
|
25
|
+
let input = {};
|
|
26
|
+
try { input = JSON.parse(raw); } catch { input = {}; }
|
|
27
|
+
const sessionId = input.session_id || 'unknown';
|
|
28
|
+
const cwd = input.cwd || process.cwd();
|
|
29
|
+
const reason = input.reason || 'unknown';
|
|
30
|
+
|
|
31
|
+
// Log session end.
|
|
32
|
+
try {
|
|
33
|
+
const logDir = path.join(os.homedir(), '.config', 'bizar', 'hook-logs');
|
|
34
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
35
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
36
|
+
const logFile = path.join(logDir, `session-end-${today}.jsonl`);
|
|
37
|
+
fs.appendFileSync(logFile, JSON.stringify({
|
|
38
|
+
ts: new Date().toISOString(),
|
|
39
|
+
sessionId,
|
|
40
|
+
reason,
|
|
41
|
+
cwd,
|
|
42
|
+
}) + '\n');
|
|
43
|
+
} catch { /* best-effort */ }
|
|
44
|
+
|
|
45
|
+
// Write a session note to the memory vault.
|
|
46
|
+
const vaultRoot = process.env.BIZAR_MEMORY_VAULT || path.join(os.homedir(), '.bizar_memory');
|
|
47
|
+
const projectName = path.basename(cwd) || 'unknown';
|
|
48
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
49
|
+
const notePath = path.join(vaultRoot, 'projects', projectName, 'sessions', `${date}-${sessionId.slice(0, 8)}.md`);
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
fs.mkdirSync(path.dirname(notePath), { recursive: true });
|
|
53
|
+
const noteBody = [
|
|
54
|
+
'---',
|
|
55
|
+
`title: Session ${sessionId.slice(0, 8)}`,
|
|
56
|
+
`createdAt: ${new Date().toISOString()}`,
|
|
57
|
+
`sessionId: ${sessionId}`,
|
|
58
|
+
`cwd: ${cwd}`,
|
|
59
|
+
`reason: ${reason}`,
|
|
60
|
+
'tags: [session, auto-generated]',
|
|
61
|
+
'---',
|
|
62
|
+
'',
|
|
63
|
+
`# Session ${sessionId.slice(0, 8)} (${date})`,
|
|
64
|
+
'',
|
|
65
|
+
`Session ended with reason: \`${reason}\`.`,
|
|
66
|
+
'',
|
|
67
|
+
`Working directory: \`${cwd}\``,
|
|
68
|
+
'',
|
|
69
|
+
].join('\n');
|
|
70
|
+
fs.writeFileSync(notePath, noteBody, 'utf8');
|
|
71
|
+
} catch { /* best-effort */ }
|
|
72
|
+
|
|
73
|
+
process.stdout.write(JSON.stringify({}) + '\n');
|
|
74
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SessionStart — Bizar harness hook (Claude Code format).
|
|
3
|
+
//
|
|
4
|
+
// Claude Code has a single `SessionStart` event that fires for
|
|
5
|
+
// "startup", "clear", and "resume" — we branch on `source` to apply
|
|
6
|
+
// the appropriate priming for each branch.
|
|
7
|
+
//
|
|
8
|
+
// Claude Code stdin shape:
|
|
9
|
+
// {
|
|
10
|
+
// "session_id": "...",
|
|
11
|
+
// "transcript_path": "...",
|
|
12
|
+
// "cwd": "...",
|
|
13
|
+
// "hook_event_name": "SessionStart",
|
|
14
|
+
// "source": "startup" | "resume" | "clear"
|
|
15
|
+
// }
|
|
16
|
+
//
|
|
17
|
+
// Claude Code stdout shape:
|
|
18
|
+
// { "hookSpecificOutput": {
|
|
19
|
+
// "hookEventName": "SessionStart",
|
|
20
|
+
// "additionalContext": "note injected into the model's first turn"
|
|
21
|
+
// }}
|
|
22
|
+
|
|
23
|
+
'use strict';
|
|
24
|
+
|
|
25
|
+
import fs from 'node:fs';
|
|
26
|
+
import os from 'node:os';
|
|
27
|
+
import path from 'node:path';
|
|
28
|
+
|
|
29
|
+
let raw = '';
|
|
30
|
+
process.stdin.setEncoding('utf8');
|
|
31
|
+
process.stdin.on('data', (chunk) => { raw += chunk; });
|
|
32
|
+
process.stdin.on('end', () => {
|
|
33
|
+
let input = {};
|
|
34
|
+
try { input = JSON.parse(raw || '{}'); } catch { input = {}; }
|
|
35
|
+
|
|
36
|
+
// "startup" | "resume" | "clear" — default to "startup".
|
|
37
|
+
const source = String(input.source || 'startup');
|
|
38
|
+
const sessionId = String(input.session_id || '');
|
|
39
|
+
const isResume = source === 'resume';
|
|
40
|
+
|
|
41
|
+
// Log session lifecycle to ~/.config/bizar/hook-logs/.
|
|
42
|
+
try {
|
|
43
|
+
const logDir = path.join(os.homedir(), '.config', 'bizar', 'hook-logs');
|
|
44
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
45
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
46
|
+
const logFile = isResume
|
|
47
|
+
? path.join(logDir, `task-resume-${today}.jsonl`)
|
|
48
|
+
: path.join(logDir, `task-start-${today}.jsonl`);
|
|
49
|
+
const line = JSON.stringify({
|
|
50
|
+
ts: new Date().toISOString(),
|
|
51
|
+
sessionId: sessionId || null,
|
|
52
|
+
source,
|
|
53
|
+
initial: isResume ? '' : 'bizar:sessionstart:' + source,
|
|
54
|
+
});
|
|
55
|
+
fs.appendFileSync(logFile, line + '\n');
|
|
56
|
+
} catch { /* best-effort */ }
|
|
57
|
+
|
|
58
|
+
const notes = isResume
|
|
59
|
+
? [
|
|
60
|
+
'Bizar SessionStart (resume): re-read `.bizar/PROJECT.md` and `PROGRESS.md` before continuing.',
|
|
61
|
+
'Bizar SessionStart (resume): check `git log --oneline -10` to see what changed since the last run.',
|
|
62
|
+
// Claude Code compacts context automatically between resumes;
|
|
63
|
+
// compaction is opaque to the hook, so we warn unconditionally
|
|
64
|
+
// to remind the agent to verify scope.
|
|
65
|
+
'Bizar SessionStart (resume): WARNING — context may have been compacted since the last run; verify scope before continuing.',
|
|
66
|
+
]
|
|
67
|
+
: [
|
|
68
|
+
'Bizar SessionStart: read `.bizar/PROJECT.md` (if present) before any routing decision.',
|
|
69
|
+
'Bizar SessionStart: if memory vault exists, run `bizar memory search "<topic>"` first.',
|
|
70
|
+
'Bizar SessionStart: Odin dispatches to subagents via `Agent` (sync) or via the `bizar-mcp` MCP server (async).',
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
const out = {
|
|
74
|
+
hookSpecificOutput: {
|
|
75
|
+
hookEventName: 'SessionStart',
|
|
76
|
+
additionalContext: notes.join(' '),
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
process.stdout.write(JSON.stringify(out) + '\n');
|
|
80
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// UserPromptSubmit — Bizar harness hook (Claude Code format).
|
|
3
|
+
//
|
|
4
|
+
// Runs when the user submits a prompt. Lightly tags the prompt for
|
|
5
|
+
// routing and emits a short routing hint for the model's next turn.
|
|
6
|
+
//
|
|
7
|
+
// Claude Code stdin shape:
|
|
8
|
+
// {
|
|
9
|
+
// "session_id": "...",
|
|
10
|
+
// "transcript_path": "...",
|
|
11
|
+
// "cwd": "...",
|
|
12
|
+
// "hook_event_name": "UserPromptSubmit",
|
|
13
|
+
// "user_prompt": "raw prompt text"
|
|
14
|
+
// }
|
|
15
|
+
//
|
|
16
|
+
// Claude Code stdout shape:
|
|
17
|
+
// { "hookSpecificOutput": {
|
|
18
|
+
// "hookEventName": "UserPromptSubmit",
|
|
19
|
+
// "additionalContext": "routing hint for the model"
|
|
20
|
+
// }}
|
|
21
|
+
//
|
|
22
|
+
// Behaviour:
|
|
23
|
+
// 1. Append-only JSONL log of (timestamp, sessionId, promptLength).
|
|
24
|
+
// 2. Branch on leading slash-command: empty / /team / /plow-through /
|
|
25
|
+
// /test / /validate / default-decompose.
|
|
26
|
+
|
|
27
|
+
'use strict';
|
|
28
|
+
|
|
29
|
+
import fs from 'node:fs';
|
|
30
|
+
import os from 'node:os';
|
|
31
|
+
import path from 'node:path';
|
|
32
|
+
|
|
33
|
+
let raw = '';
|
|
34
|
+
process.stdin.setEncoding('utf8');
|
|
35
|
+
process.stdin.on('data', (chunk) => { raw += chunk; });
|
|
36
|
+
process.stdin.on('end', () => {
|
|
37
|
+
let input = {};
|
|
38
|
+
try { input = JSON.parse(raw || '{}'); } catch { input = {}; }
|
|
39
|
+
|
|
40
|
+
const prompt = String(input.user_prompt || '').trim();
|
|
41
|
+
const sessionId = String(input.session_id || '');
|
|
42
|
+
|
|
43
|
+
// 1. Always log (no PII redaction needed — the prompt is the user's).
|
|
44
|
+
try {
|
|
45
|
+
const logDir = path.join(os.homedir(), '.config', 'bizar', 'hook-logs');
|
|
46
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
47
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
48
|
+
const logFile = path.join(logDir, `user-prompt-${today}.jsonl`);
|
|
49
|
+
const line = JSON.stringify({
|
|
50
|
+
ts: new Date().toISOString(),
|
|
51
|
+
sessionId: sessionId || null,
|
|
52
|
+
promptLength: prompt.length,
|
|
53
|
+
});
|
|
54
|
+
fs.appendFileSync(logFile, line + '\n');
|
|
55
|
+
} catch { /* best-effort */ }
|
|
56
|
+
|
|
57
|
+
// 2. Branch on leading slash-command (anchored to start of trimmed text).
|
|
58
|
+
let note;
|
|
59
|
+
if (prompt.length === 0) {
|
|
60
|
+
note = 'Bizar UserPromptSubmit: empty prompt — wait for actual user input.';
|
|
61
|
+
} else if (prompt.startsWith('/team')) {
|
|
62
|
+
note = 'Bizar UserPromptSubmit: /team — Odin will spawn a coordinated agent team. Confirm disjoint file scopes before dispatching.';
|
|
63
|
+
} else if (prompt.startsWith('/plow-through')) {
|
|
64
|
+
note = 'Bizar UserPromptSubmit: /plow-through — autonomous mode. Dispatch 2+ parallel agents when possible. Run /test before claiming done.';
|
|
65
|
+
} else if (prompt.startsWith('/test')) {
|
|
66
|
+
note = 'Bizar UserPromptSubmit: /test — auto-detects runner (jest/vitest/bun/pytest/cargo/go). Streams output to the user.';
|
|
67
|
+
} else if (prompt.startsWith('/validate')) {
|
|
68
|
+
note = 'Bizar UserPromptSubmit: /validate — runs 21-point health check on the Bizar install.';
|
|
69
|
+
} else {
|
|
70
|
+
note = 'Bizar UserPromptSubmit: if the request is complex, decompose into 2+ parallel subagent tasks (Odin) or spawn a /team.';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const out = {
|
|
74
|
+
hookSpecificOutput: {
|
|
75
|
+
hookEventName: 'UserPromptSubmit',
|
|
76
|
+
additionalContext: note,
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
process.stdout.write(JSON.stringify(out) + '\n');
|
|
80
|
+
});
|