@polderlabs/bizar 2.3.0 → 2.4.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/cli/copy.mjs CHANGED
@@ -269,8 +269,11 @@ export async function installPluginBizar(projectRoot) {
269
269
  try {
270
270
  await access(srcDir, constants.F_OK);
271
271
  } catch {
272
- spinner.warn(chalk.yellow('Bizar plugin source not found skipping'));
273
- return { copied: 0, errors: ['Source not found: ' + srcDir] };
272
+ // The Bizar plugin now lives in a separate npm package
273
+ // (@polderlabs/bizar-plugin). The interactive installer copies it from
274
+ // there; the source tree no longer carries plugins/bizar/.
275
+ // Silent return — no warning needed.
276
+ return { copied: 0, errors: [] };
274
277
  }
275
278
 
276
279
  const destDir = join(projectRoot, '.opencode', 'plugins', 'bizar');
@@ -506,3 +509,40 @@ export async function installCommands() {
506
509
  }
507
510
  return count;
508
511
  }
512
+
513
+ /**
514
+ * Install Bizar-specific commands to commands-bizar/ (separate from ECC's
515
+ * commands/ symlink). This directory holds the Bizar plugin's own command
516
+ * templates: audit, explain, init, learn, plan, pr-review, tailscale-serve,
517
+ * visual-plan, and bizar.
518
+ *
519
+ * If dest is a symlink (e.g. the ECC installer symlinked it), skip with a
520
+ * friendly message — we don't want to follow a symlink and write into someone
521
+ * else's directory.
522
+ *
523
+ * @returns {Promise<number>} count of .md files copied
524
+ */
525
+ export async function installCommandsBizar() {
526
+ const src = repoPath('config', 'commands');
527
+ const dest = join(opencodeConfigDir(), 'commands-bizar');
528
+ const { mkdirSync, readdirSync, copyFileSync, lstatSync } = await import('node:fs');
529
+
530
+ // Guard: skip if dest is a symlink (don't follow other packages' symlinks)
531
+ try {
532
+ const stat = lstatSync(dest);
533
+ if (stat.isSymbolicLink()) {
534
+ console.log('BizarHarness: commands-bizar/ is a symlink — skipping install.');
535
+ return 0;
536
+ }
537
+ } catch {
538
+ // dest does not exist — that's fine, we'll create it
539
+ }
540
+
541
+ mkdirSync(dest, { recursive: true });
542
+ let count = 0;
543
+ for (const file of readdirSync(src).filter(f => f.endsWith('.md'))) {
544
+ copyFileSync(join(src, file), join(dest, file));
545
+ count++;
546
+ }
547
+ return count;
548
+ }
package/cli/install.mjs CHANGED
@@ -1,11 +1,12 @@
1
1
  import chalk from 'chalk';
2
2
  import boxen from 'boxen';
3
3
  import { existsSync } from 'node:fs';
4
+ import { join } from 'node:path';
4
5
 
5
6
  import { showBanner, showPantheon, sectionHeading } from './banner.mjs';
6
7
  import { promptComponents, promptInstallMode, promptAgents, promptSkillPacks, promptApiKeys, promptConfirmInstall, promptRestartOpenCode } from './prompts.mjs';
7
8
  import { detectOpenCode, detectRtk, detectSemble, detectSkillsCli, buildSummary, opencodeAgentsDir, opencodeConfigDir, repoPath } from './utils.mjs';
8
- import { installAgents, installAgentsMd, installSkill, installOpencodeJson, installBizarFolder, installPluginBizar, installRtk, installSemble, installSkillsCli, installCuratedSkills, installRules, installHooks, installCommands, mergeToolsIntoUserConfig } from './copy.mjs';
9
+ import { installAgents, installAgentsMd, installSkill, installOpencodeJson, installBizarFolder, installPluginBizar, installRtk, installSemble, installSkillsCli, installCuratedSkills, installRules, installHooks, installCommands, installCommandsBizar, mergeToolsIntoUserConfig } from './copy.mjs';
9
10
 
10
11
  const AGENT_FILES = [
11
12
  'odin.md', 'vor.md', 'frigg.md', 'quick.md',
@@ -295,13 +296,25 @@ export async function runInstaller() {
295
296
 
296
297
  export async function runPostInstall() {
297
298
  const { mkdirSync, copyFileSync, existsSync } = await import('node:fs');
298
- const { join } = await import('node:path');
299
299
  const { execSync } = await import('node:child_process');
300
300
 
301
+ const dest = join(opencodeConfigDir(), 'opencode.json');
302
+ const templateSrc = repoPath('config', 'opencode.json');
303
+ if (!existsSync(dest)) {
304
+ if (existsSync(templateSrc)) {
305
+ mkdirSync(opencodeConfigDir(), { recursive: true });
306
+ copyFileSync(templateSrc, dest);
307
+ console.log(' ✓ opencode.json bootstrapped from package template');
308
+ }
309
+ }
310
+
311
+ // Install Bizar commands to commands-bizar/ (separate from ECC's commands symlink)
312
+ await installCommandsBizar();
313
+
301
314
  const env = await detectOpenCode();
302
315
  if (!env.exists) {
303
- console.log('BizarHarness: opencode not detected — skipping auto-install.');
304
- return;
316
+ mkdirSync(opencodeConfigDir(), { recursive: true });
317
+ console.log('BizarHarness: created ~/.config/opencode/');
305
318
  }
306
319
 
307
320
  mkdirSync(opencodeAgentsDir(), { recursive: true });
@@ -0,0 +1,44 @@
1
+ # Bizar Plugin Menu
2
+
3
+ You are @odin, the routing agent. The user invoked /bizar. They wrote: $ARGUMENTS
4
+
5
+ Based on their request, route them to the right Bizar action.
6
+
7
+ ## Available commands
8
+
9
+ - `/visual-plan on|off|status` — Toggle the Bizar visual plan canvas
10
+ - `/plan new <slug> [template]` — Create a new visual plan
11
+ - `/plan list` — List existing plans
12
+ - `/plan open <slug>` — Open a plan
13
+ - `/plan get <slug>` — Get plan content
14
+ - `/plan add <slug> --title "..."` — Add element to plan
15
+ - `/plan update <slug> <id> ...` — Update element
16
+ - `/plan delete <slug> <id>` — Delete element
17
+ - `/plan comment <slug> [id] "..."` — Add comment
18
+ - `/plan comments <slug> [id]` — List comments
19
+ - `/plan status <slug> <status>` — Set plan status
20
+ - `/plan wait <slug>` — Wait for plan feedback
21
+ - `/audit` — Run a security audit
22
+ - `/explain <question>` — Read-only Q&A (routes to @frigg)
23
+ - `/init` — Initialize Bizar in the current project
24
+ - `/learn` — Extract patterns from the session (routes to @heimdall)
25
+ - `/pr-review` — Run a PR review with @mimir + @forseti (routes to @hermod)
26
+ - `/tailscale-serve` — Set up Tailscale Serve
27
+
28
+ ## Routing rules
29
+
30
+ 1. If the user wants to read code or understand something without changes → invoke `/explain` or answer as @frigg
31
+ 2. If the user wants to plan work visually → `/visual-plan on` then `/plan new <slug>`
32
+ 3. If the user wants to do a security audit → `/audit`
33
+ 4. If the user wants to review a PR → `/pr-review`
34
+ 5. If the user wants to learn patterns from a session → `/learn`
35
+ 6. If the user wants to initialize Bizar → `/init`
36
+ 7. Otherwise, ask a clarifying question and route to the appropriate sub-agent
37
+
38
+ ## Response format
39
+
40
+ Briefly explain what you'll do, then either:
41
+ - Run the appropriate slash command, OR
42
+ - Ask one clarifying question if the request is ambiguous
43
+
44
+ Never make changes to the codebase. You are a router, not an executor.
@@ -0,0 +1,26 @@
1
+ Open or manage a Bizar visual plan. Plans are collaborative canvases for structuring work across agents.
2
+
3
+ ## Usage
4
+
5
+ ```
6
+ /plan new <slug> [template] — Create a new plan with a unique slug
7
+ /plan list — List all existing plans
8
+ /plan open <slug> — Open a plan (returns the canvas URL)
9
+ /plan get <slug> — Get full plan content as JSON
10
+ /plan add <slug> --title "..." — Add a new element to a plan
11
+ /plan update <slug> <id> ... — Update an element's content/title/status
12
+ /plan delete <slug> <id> — Delete an element from a plan
13
+ /plan comment <slug> [id] "..." — Add a comment to a plan or element
14
+ /plan comments <slug> [id] — List comments on a plan or element
15
+ /plan status <slug> <status> — Set plan status (draft|approved|rejected|in-progress|done)
16
+ /plan wait <slug> — Block until the plan receives feedback
17
+ ```
18
+
19
+ ## Routing
20
+
21
+ - If the user wants to create a new plan → `/plan new <slug>`
22
+ - If the user wants to see existing plans → `/plan list`
23
+ - If the user wants to open/view a plan → `/plan open <slug>`
24
+ - If the user wants to add content to a plan → `/plan add <slug> --title "..."`
25
+ - If the user wants to modify a plan element → `/plan update <slug> <id> ...`
26
+ - If the user wants to discuss/approve/reject → `/plan status <slug> <status>`
@@ -0,0 +1,15 @@
1
+ Toggle the Bizar visual plan canvas or check its current status.
2
+
3
+ ## Usage
4
+
5
+ ```
6
+ /visual-plan on — Enable the visual plan canvas in the current session
7
+ /visual-plan off — Disable the visual plan canvas
8
+ /visual-plan status — Show whether the canvas is currently enabled
9
+ ```
10
+
11
+ ## Notes
12
+
13
+ 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.
14
+
15
+ This is a session-level toggle — it affects the current opencode session only.
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://opencode.ai/config.json",
3
3
  "model": "minimax/MiniMax-M3",
4
4
  "small_model": "minimax/MiniMax-M2.7",
5
- "default_agent": "quick",
5
+ "default_agent": "odin",
6
6
  "permission": "allow",
7
7
  "snapshot": false,
8
8
  "mcp": {
@@ -48,5 +48,263 @@
48
48
  "bizar_status": true,
49
49
  "bizar_collect": true,
50
50
  "bizar_kill": true
51
+ },
52
+ "agent": {
53
+ "odin": {
54
+ "description": "Odin — Pure router that delegates all work to subagents. Routes across Frigg (DeepSeek/Q&A), Vör (DeepSeek/clarify), Mimir (DeepSeek/research), Heimdall (DeepSeek/simple), Hermod (M2.7/git), Thor (M2.7/mid), Baldr (M2.7/design), Tyr (M3/top), Vidarr (GPT-5.5/ultra), Forseti (verifier/M3).",
55
+ "mode": "primary",
56
+ "model": "minimax/MiniMax-M3",
57
+ "color": "#6366f1",
58
+ "permission": {
59
+ "task": "allow",
60
+ "read": "allow",
61
+ "list": "allow",
62
+ "todowrite": "allow",
63
+ "webfetch": "allow",
64
+ "websearch": "allow"
65
+ }
66
+ },
67
+ "vor": {
68
+ "description": "Vör — The Questioning One. When a task is ambiguous, incomplete, or unclear, Vör asks the right clarifying questions before any work begins.",
69
+ "mode": "subagent",
70
+ "model": "minimax/MiniMax-M2.7",
71
+ "color": "#8b5cf6",
72
+ "permission": {
73
+ "read": "allow",
74
+ "list": "allow",
75
+ "question": "allow",
76
+ "hindsight_recall": "allow",
77
+ "hindsight_retain": "allow"
78
+ }
79
+ },
80
+ "frigg": {
81
+ "description": "Frigg — All-knowing Q&A agent. Read-only codebase questions and answers. Never edits, never writes, only answers.",
82
+ "mode": "primary",
83
+ "model": "minimax/MiniMax-M2.7",
84
+ "color": "#06b6d4",
85
+ "permission": {
86
+ "read": "allow",
87
+ "list": "allow",
88
+ "glob": "allow",
89
+ "grep": "allow",
90
+ "bash": "allow",
91
+ "webfetch": "allow",
92
+ "websearch": "allow",
93
+ "hindsight_recall": "allow",
94
+ "hindsight_retain": "allow",
95
+ "question": "allow"
96
+ }
97
+ },
98
+ "quick": {
99
+ "description": "Quick — Fast single-shot tasks. No delegation, no parallel streams. Use for small edits, mechanical changes, one-shot questions. Routes to no one.",
100
+ "mode": "primary",
101
+ "model": "minimax/MiniMax-M2.7",
102
+ "color": "#22d3ee",
103
+ "permission": {
104
+ "read": "allow",
105
+ "edit": "allow",
106
+ "write": "allow",
107
+ "bash": "allow",
108
+ "glob": "allow",
109
+ "grep": "allow",
110
+ "list": "allow",
111
+ "todowrite": "allow",
112
+ "webfetch": "allow",
113
+ "websearch": "allow",
114
+ "task": "deny"
115
+ }
116
+ },
117
+ "mimir": {
118
+ "description": "Mimir — Dedicated research and codebase exploration agent. Uses Semble as primary search tool. Deep codebase analysis, pattern discovery, and documentation research.",
119
+ "mode": "subagent",
120
+ "model": "minimax/MiniMax-M2.7",
121
+ "color": "#0ea5e9",
122
+ "permission": {
123
+ "read": "allow",
124
+ "write": "allow",
125
+ "edit": "allow",
126
+ "bash": "allow",
127
+ "glob": "allow",
128
+ "grep": "allow",
129
+ "list": "allow",
130
+ "webfetch": "allow",
131
+ "websearch": "allow",
132
+ "todowrite": "allow"
133
+ }
134
+ },
135
+ "heimdall": {
136
+ "description": "Heimdall — Simple, routine, and deterministic tasks using DeepSeek. Quick edits, mechanical work, file operations. The ever-watchful guardian.",
137
+ "mode": "subagent",
138
+ "model": "minimax/MiniMax-M2.7",
139
+ "color": "#10b981",
140
+ "permission": {
141
+ "read": "allow",
142
+ "edit": "allow",
143
+ "bash": "allow",
144
+ "glob": "allow",
145
+ "grep": "allow",
146
+ "list": "allow",
147
+ "todowrite": "allow",
148
+ "webfetch": "allow",
149
+ "websearch": "allow"
150
+ }
151
+ },
152
+ "hermod": {
153
+ "description": "Hermod — Git and GitHub operations specialist using MiniMax M2.7. Branching, commits, PRs, merge/rebase, conflict resolution, CI/CD, releases, gh CLI.",
154
+ "mode": "subagent",
155
+ "model": "minimax/MiniMax-M2.7",
156
+ "color": "#06b6d4",
157
+ "permission": {
158
+ "read": "allow",
159
+ "edit": "allow",
160
+ "bash": "allow",
161
+ "glob": "allow",
162
+ "grep": "allow",
163
+ "list": "allow",
164
+ "webfetch": "allow",
165
+ "websearch": "allow"
166
+ }
167
+ },
168
+ "thor": {
169
+ "description": "Thor — Handles medium-complexity tasks using MiniMax M2.7 from minimax.io. Strong and reliable, cheaper than Tyr but more capable than Heimdall.",
170
+ "mode": "subagent",
171
+ "model": "minimax/MiniMax-M2.7",
172
+ "color": "#a855f7",
173
+ "permission": {
174
+ "read": "allow",
175
+ "edit": "allow",
176
+ "bash": "allow",
177
+ "glob": "allow",
178
+ "grep": "allow",
179
+ "list": "allow",
180
+ "todowrite": "allow",
181
+ "webfetch": "allow",
182
+ "websearch": "allow"
183
+ }
184
+ },
185
+ "baldr": {
186
+ "description": "Baldr — UI/UX design system specialist. Creates DESIGN.md files using Google's design.md standard. Focuses on visual consistency, usability, accessibility, and design tokens.",
187
+ "mode": "subagent",
188
+ "model": "minimax/MiniMax-M2.7",
189
+ "color": "#ec4899",
190
+ "permission": {
191
+ "read": "allow",
192
+ "edit": "allow",
193
+ "bash": "allow",
194
+ "glob": "allow",
195
+ "grep": "allow",
196
+ "list": "allow",
197
+ "todowrite": "allow",
198
+ "webfetch": "allow",
199
+ "websearch": "allow"
200
+ }
201
+ },
202
+ "tyr": {
203
+ "description": "Tyr — Handles the most complex implementation, debugging, and architectural work using MiniMax M3 via minimax.io. Unmatched wisdom for the hardest problems.",
204
+ "mode": "subagent",
205
+ "model": "minimax/MiniMax-M3",
206
+ "color": "#f59e0b",
207
+ "permission": {
208
+ "read": "allow",
209
+ "edit": "allow",
210
+ "bash": "allow",
211
+ "glob": "allow",
212
+ "grep": "allow",
213
+ "list": "allow",
214
+ "todowrite": "allow",
215
+ "webfetch": "allow",
216
+ "websearch": "allow"
217
+ }
218
+ },
219
+ "vidarr": {
220
+ "description": "Vidarr — The ultimate fallback using GPT-5.5 via OpenAI ChatGPT subscription. For the hardest problems when debugging stalls or nothing else works. Use sparingly — highest cost.",
221
+ "mode": "subagent",
222
+ "model": "openai/gpt-5.5",
223
+ "color": "#dc2626",
224
+ "permission": {
225
+ "read": "allow",
226
+ "edit": "allow",
227
+ "bash": "allow",
228
+ "glob": "allow",
229
+ "grep": "allow",
230
+ "list": "allow",
231
+ "todowrite": "allow",
232
+ "webfetch": "allow",
233
+ "websearch": "allow"
234
+ }
235
+ },
236
+ "forseti": {
237
+ "description": "Forseti — Audits, criticizes, and corrects implementation plans before execution using MiniMax M3. No write permissions — review only.",
238
+ "mode": "subagent",
239
+ "model": "minimax/MiniMax-M3",
240
+ "color": "#ef4444",
241
+ "permission": {
242
+ "read": "allow",
243
+ "edit": "deny",
244
+ "bash": "allow",
245
+ "glob": "allow",
246
+ "grep": "allow",
247
+ "list": "allow",
248
+ "todowrite": "allow",
249
+ "question": "allow",
250
+ "webfetch": "allow",
251
+ "websearch": "allow"
252
+ }
253
+ },
254
+ "semble-search": {
255
+ "description": "Code search agent for exploring any codebase. Use for finding code by intent, locating implementations, understanding how something works.",
256
+ "mode": "subagent",
257
+ "permission": {
258
+ "bash": "allow",
259
+ "read": "allow"
260
+ }
261
+ }
262
+ },
263
+ "command": {
264
+ "audit": {
265
+ "description": "Run bizar audit to scan agent configuration for security issues.",
266
+ "agent": "forseti",
267
+ "template": "commands-bizar/audit.md"
268
+ },
269
+ "explain": {
270
+ "description": "Route to @frigg for read-only codebase Q&A. She will explore the code and answer without making any changes.",
271
+ "agent": "frigg",
272
+ "template": "commands-bizar/explain.md"
273
+ },
274
+ "init": {
275
+ "description": "Run bizar init to detect project stack, install relevant skills, and create .bizar/PROJECT.md.",
276
+ "agent": "heimdall",
277
+ "template": "commands-bizar/init.md"
278
+ },
279
+ "learn": {
280
+ "description": "Route to @heimdall. Extract patterns from the current session and append to .bizar/AGENTS_SELF_IMPROVEMENT.md.",
281
+ "agent": "heimdall",
282
+ "template": "commands-bizar/learn.md"
283
+ },
284
+ "plan": {
285
+ "description": "Open the Bizar visual plan canvas or manage existing plans.",
286
+ "agent": "odin",
287
+ "template": "commands-bizar/plan.md"
288
+ },
289
+ "pr-review": {
290
+ "description": "Route to @hermod for PR review mode. Launches @mimir (research) and @forseti (audit) in parallel, then posts the combined review as a PR comment.",
291
+ "agent": "hermod",
292
+ "template": "commands-bizar/pr-review.md"
293
+ },
294
+ "tailscale-serve": {
295
+ "description": "Authenticate Tailscale Serve and expose a local port on your tailnet.",
296
+ "agent": "heimdall",
297
+ "template": "commands-bizar/tailscale-serve.md"
298
+ },
299
+ "visual-plan": {
300
+ "description": "Toggle the Bizar visual plan canvas on or off, or check its current status.",
301
+ "agent": "odin",
302
+ "template": "commands-bizar/visual-plan.md"
303
+ },
304
+ "bizar": {
305
+ "description": "Bizar Plugin Menu — route to the right Bizar action based on the user's request.",
306
+ "agent": "odin",
307
+ "template": "commands-bizar/bizar.md\n\n$ARGUMENTS"
308
+ }
51
309
  }
52
310
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polderlabs/bizar",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "Norse-pantheon multi-agent system for opencode — 13 agents across 4 cost tiers with cost-aware routing and per-project Hindsight memory",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,52 +0,0 @@
1
- {
2
- "$schema": "https://opencode.ai/config.json",
3
- "model": "opencode/deepseek-v4-flash-free",
4
- "small_model": "opencode/deepseek-v4-flash-free",
5
- "default_agent": "odin",
6
- "permission": "allow",
7
- "snapshot": false,
8
- "mcp": {
9
- "supabase": {
10
- "type": "remote",
11
- "url": "https://mcp.supabase.com/mcp",
12
- "enabled": true
13
- },
14
- "hindsight": {
15
- "type": "remote",
16
- "url": "https://memory-api.polderlabs.io/mcp",
17
- "enabled": true,
18
- "oauth": false,
19
- "headers": {
20
- "Authorization": "Bearer YOUR_HINDSIGHT_API_KEY",
21
- "Content-Type": "application/json"
22
- }
23
- },
24
- "semble": {
25
- "type": "local",
26
- "command": [
27
- "uvx",
28
- "--from",
29
- "semble[mcp]",
30
- "semble"
31
- ],
32
- "enabled": true
33
- }
34
- },
35
- "plugin": [
36
- ["./plugins/bizar/index.ts", {
37
- "loopThresholdWarn": 5,
38
- "loopThresholdEscalate": 8,
39
- "loopThresholdBlock": 12,
40
- "loopWindowSize": 10
41
- }]
42
- ],
43
- "tools": {
44
- "bizar_plan_action": true,
45
- "bizar_get_plan_comments": true,
46
- "bizar_wait_for_feedback": true,
47
- "bizar_spawn_background": true,
48
- "bizar_status": true,
49
- "bizar_collect": true,
50
- "bizar_kill": true
51
- }
52
- }