brainclaw 0.19.12 → 0.20.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.
Files changed (40) hide show
  1. package/README.md +42 -11
  2. package/dist/cli.js +55 -1
  3. package/dist/commands/claude-desktop-extension.js +18 -0
  4. package/dist/commands/context.js +3 -1
  5. package/dist/commands/doctor.js +12 -5
  6. package/dist/commands/export.js +44 -0
  7. package/dist/commands/init.js +22 -6
  8. package/dist/commands/list-surface-tasks.js +39 -0
  9. package/dist/commands/mcp.js +86 -5
  10. package/dist/commands/reconcile.js +138 -0
  11. package/dist/commands/setup.js +19 -0
  12. package/dist/commands/status.js +17 -12
  13. package/dist/commands/surface-task-resource.js +35 -0
  14. package/dist/commands/surface-task.js +57 -0
  15. package/dist/commands/uninstall.js +145 -0
  16. package/dist/commands/update-surface-task.js +30 -0
  17. package/dist/core/agent-capability.js +184 -0
  18. package/dist/core/agent-context.js +24 -6
  19. package/dist/core/agent-files.js +18 -18
  20. package/dist/core/ai-surface-inventory.js +321 -0
  21. package/dist/core/ai-surface-tasks.js +40 -0
  22. package/dist/core/bootstrap.js +177 -0
  23. package/dist/core/claude-desktop-extension.js +224 -0
  24. package/dist/core/context.js +47 -24
  25. package/dist/core/ids.js +1 -0
  26. package/dist/core/instruction-templates.js +308 -0
  27. package/dist/core/io.js +1 -0
  28. package/dist/core/machine-profile.js +7 -1
  29. package/dist/core/migration.js +3 -1
  30. package/dist/core/schema.js +34 -0
  31. package/dist/core/setup-flow.js +191 -0
  32. package/dist/core/setup-state.js +30 -1
  33. package/dist/core/store-resolution.js +58 -0
  34. package/dist/core/workspace-projects.js +115 -0
  35. package/docs/architecture/project-refs.md +305 -0
  36. package/docs/cli.md +133 -1
  37. package/docs/integrations/agents.md +102 -150
  38. package/docs/integrations/overview.md +71 -45
  39. package/docs/quickstart.md +44 -111
  40. package/package.json +1 -1
package/README.md CHANGED
@@ -21,6 +21,8 @@ The best setup is to tell your agent, in natural language, to install and initia
21
21
 
22
22
  It sits alongside Copilot, Claude Code, Cursor, Codex, Windsurf, OpenCode, Antigravity/Gemini CLI and other coding agents. It does not replace them. It gives them a shared state layer they can resume from reliably across sessions.
23
23
 
24
+ brainclaw is also starting to model other local AI work surfaces on the same machine, such as ChatGPT Desktop, Claude Desktop, Claude Cowork, and Gemini web or CLI. That makes it possible to keep a project-level queue of non-code work for those surfaces, instead of treating every task as something the active coding agent must do itself.
25
+
24
26
  ---
25
27
 
26
28
  ## Why brainclaw exists
@@ -40,6 +42,8 @@ brainclaw solves this by making the repo itself agent-readable and agent-writeab
40
42
  | **Coordination state** | shared plans, file claims, runtime notes, and board views for active work |
41
43
  | **Agent-ready context** | compact, prompt-sized context built from real workspace state instead of stale instructions |
42
44
  | **Native agent files** | auto-writes `CLAUDE.md`, `AGENTS.md`, `GEMINI.md`, `.cursor/rules/`, `.windsurfrules`, and similar local guidance |
45
+ | **Machine AI surface discovery** | detects local coding agents plus desktop AI work surfaces such as ChatGPT Desktop and Gemini CLI |
46
+ | **Queued surface tasks** | stores project-scoped requests for other local AI surfaces, such as visual generation, drafting, summaries, or research |
43
47
  | **Local-first storage** | plain text + JSON, Git-friendly, no mandatory cloud, no telemetry by default |
44
48
 
45
49
  ---
@@ -62,18 +66,20 @@ If you are documenting or integrating an agent workflow, treat MCP as the primar
62
66
 
63
67
  brainclaw is designed to sit alongside the coding agents teams are already using, not behind a separate hosted control plane.
64
68
 
65
- | Logo | Agent | Brainclaw fit | Best use today |
69
+ | Logo | Agent | Integration | What brainclaw configures |
66
70
  |---|---|---|---|
67
- | [![Claude Code](https://img.shields.io/badge/Claude_Code-111111?logo=anthropic&logoColor=white)](https://github.com/anthropics/claude-code) | **[Claude Code](https://github.com/anthropics/claude-code)** | Best fit | full agent workflow with MCP, instructions, commands, and session hooks |
68
- | [![Codex](https://img.shields.io/badge/Codex-111111?logo=openai&logoColor=white)](https://openai.com/codex/) | **[Codex](https://openai.com/codex/)** | Strong fit | agent-first repo coordination with explicit plans, claims, and handoffs |
69
- | [![Cursor](https://img.shields.io/badge/Cursor-1F2430?logo=cursor&logoColor=white)](https://cursor.com/en-US) | **[Cursor](https://cursor.com/en-US)** | Strong fit | repo-native agent workflows with rules plus MCP |
70
- | [![OpenCode](https://img.shields.io/badge/OpenCode-0F172A?logoColor=white)](https://github.com/opencode-ai/opencode) | **[OpenCode](https://github.com/opencode-ai/opencode)** | Strong fit | simple agent bootstrap with `AGENTS.md` plus workspace MCP |
71
- | [![Windsurf](https://img.shields.io/badge/Windsurf-0B1220?logo=codeium&logoColor=white)](https://windsurf.com/) | **[Windsurf](https://windsurf.com/)** | Good fit | guided agent workflows with instructions, hooks, and MCP |
72
- | [![Roo](https://img.shields.io/badge/Roo-7C3AED?logoColor=white)](https://github.com/RooCodeInc/Roo-Code) | **[Roo](https://github.com/RooCodeInc/Roo-Code)** | Good fit | workspace agent coordination with rules plus MCP |
73
- | [![Continue](https://img.shields.io/badge/Continue-2563EB?logoColor=white)](https://github.com/continuedev/continue) | **[Continue](https://github.com/continuedev/continue)** | Good fit | editor-based agent workflows with MCP context access |
74
- | [![Gemini CLI](https://img.shields.io/badge/Gemini_CLI-1A73E8?logo=googlegemini&logoColor=white)](https://github.com/google-gemini/gemini-cli) | **[Antigravity / Gemini CLI](https://github.com/google-gemini/gemini-cli)** | Promising fit | local agent workflows with `GEMINI.md` plus MCP |
75
- | [![Cline](https://img.shields.io/badge/Cline-0F766E?logoColor=white)](https://github.com/cline/cline) | **[Cline](https://github.com/cline/cline)** | Functional fit | lightweight agent use through rules plus MCP |
76
- | [![GitHub Copilot](https://img.shields.io/badge/GitHub_Copilot-181717?logo=githubcopilot&logoColor=white)](https://github.com/features/copilot) | **[GitHub Copilot](https://github.com/features/copilot)** | Supported fit | project awareness and shared local instructions with lighter workflow control |
71
+ | [![Claude Code](https://img.shields.io/badge/Claude_Code-111111?logo=anthropic&logoColor=white)](https://github.com/anthropics/claude-code) | **[Claude Code](https://github.com/anthropics/claude-code)** | Full | MCP + CLAUDE.md + hooks + permissions + /brainclaw command |
72
+ | [![Codex](https://img.shields.io/badge/Codex-111111?logo=openai&logoColor=white)](https://openai.com/codex/) | **[Codex](https://openai.com/codex/)** | Standard | MCP + AGENTS.md |
73
+ | [![Cursor](https://img.shields.io/badge/Cursor-1F2430?logo=cursor&logoColor=white)](https://cursor.com/en-US) | **[Cursor](https://cursor.com/en-US)** | Standard | MCP + .cursor/rules/ + alwaysApply MDC |
74
+ | [![OpenCode](https://img.shields.io/badge/OpenCode-0F172A?logoColor=white)](https://github.com/opencode-ai/opencode) | **[OpenCode](https://github.com/opencode-ai/opencode)** | Standard | MCP + AGENTS.md |
75
+ | [![Windsurf](https://img.shields.io/badge/Windsurf-0B1220?logo=codeium&logoColor=white)](https://windsurf.com/) | **[Windsurf](https://windsurf.com/)** | Standard | MCP + .windsurfrules session trigger |
76
+ | [![Roo](https://img.shields.io/badge/Roo-7C3AED?logoColor=white)](https://github.com/RooCodeInc/Roo-Code) | **[Roo](https://github.com/RooCodeInc/Roo-Code)** | Standard | MCP (auto-approve) + .roo/rules/ |
77
+ | [![Cline](https://img.shields.io/badge/Cline-0F766E?logoColor=white)](https://github.com/cline/cline) | **[Cline](https://github.com/cline/cline)** | Standard | MCP (auto-approve) + .clinerules/ |
78
+ | [![Continue](https://img.shields.io/badge/Continue-2563EB?logoColor=white)](https://github.com/continuedev/continue) | **[Continue](https://github.com/continuedev/continue)** | Standard | MCP + .continue/rules/ |
79
+ | [![Gemini CLI](https://img.shields.io/badge/Gemini_CLI-1A73E8?logo=googlegemini&logoColor=white)](https://github.com/google-gemini/gemini-cli) | **[Antigravity / Gemini CLI](https://github.com/google-gemini/gemini-cli)** | Standard | MCP + GEMINI.md |
80
+ | [![GitHub Copilot](https://img.shields.io/badge/GitHub_Copilot-181717?logo=githubcopilot&logoColor=white)](https://github.com/features/copilot) | **[GitHub Copilot](https://github.com/features/copilot)** | Limited | copilot-instructions.md + brainclaw-context skill |
81
+
82
+ **Full** = MCP + hooks + auto-approve (context injected every prompt). **Standard** = MCP + instruction file (agent must call tools explicitly). **Limited** = no MCP (static instruction file is the only source of context).
77
83
 
78
84
  brainclaw is most effective today when one agent works at a time in a given checkout and the next agent resumes from shared context, claims, and handoffs.
79
85
 
@@ -146,6 +152,18 @@ brainclaw context --for src/auth/routes.ts --digest
146
152
  brainclaw status
147
153
  ```
148
154
 
155
+ And if the current coding agent wants to hand off a non-code task to another local AI surface for later:
156
+
157
+ ```bash
158
+ brainclaw surface-task create "Generate homepage hero visual" \
159
+ --target chatgpt \
160
+ --kind visual_asset \
161
+ --instructions "Create a lightweight product hero visual for the landing page." \
162
+ --output assets/hero-home.png
163
+
164
+ brainclaw surface-task list
165
+ ```
166
+
149
167
  ---
150
168
 
151
169
  ## Installation
@@ -287,6 +305,19 @@ npm run test:coverage # with coverage report
287
305
 
288
306
  ## Changelog
289
307
 
308
+ ### v0.20.0
309
+
310
+ - **Onboarding rework** : nouveau parcours d'installation en 2-3 étapes au lieu de 4, avec choix explicites (type de projet, topologie mémoire) au lieu de termes techniques
311
+ - **Agent capability profiles** : chaque agent (10 supportés) a un profil de capacité (MCP, hooks, auto-approve, skills, rules) qui détermine le contenu de ses fichiers d'instructions
312
+ - **Templates adaptatifs** : les fichiers d'instructions (CLAUDE.md, AGENTS.md, etc.) sont générés selon 3 tiers — Full (léger, hooks font le reste), Standard (directif, top traps inclus), Limited (riche, tout en statique)
313
+ - **Séparation core/run** : les fichiers statiques ne contiennent plus que le protocole, les contraintes et instructions. Les traps, plans, decisions et claims sont exclusivement dans le contexte dynamique MCP
314
+ - **Bootstrap enrichi** : scan des workflows CI/CD, ADR, CONTRIBUTING, Docker, .env.example, branches actives et tags git
315
+ - **Quick setup MCP** : `bclaw_setup` détecte le repo courant et propose un init rapide au lieu de forcer le scan multi-repo
316
+ - **`brainclaw uninstall`** : nouvelle commande pour retirer brainclaw d'un projet (`--project`) ou d'une machine (`--machine`)
317
+ - **Traps machine-scoped** : nouveau champ `platform_scope` sur les traps — les traps machine ne polluent plus les fichiers d'instructions statiques
318
+ - **Init sans setup préalable** : `brainclaw init` crée automatiquement le user store si absent, plus besoin de `brainclaw setup` d'abord
319
+ - **Docs réécrites** : intégrations, quickstart et README avec niveaux Full/Standard/Limited et matrice agent factuelle
320
+
290
321
  ### v0.9.10
291
322
 
292
323
  - **OpenCode** : détection et auto-config MCP workspace via `opencode.json`; l'export réutilise `AGENTS.md`
package/dist/cli.js CHANGED
@@ -3,6 +3,7 @@ import { Command } from 'commander';
3
3
  import { runInit } from './commands/init.js';
4
4
  import { runSetup } from './commands/setup.js';
5
5
  import { runUpgrade } from './commands/upgrade.js';
6
+ import { runReconcile } from './commands/reconcile.js';
6
7
  import { getMemoryLog, rollbackMemory, hasMemoryRepo } from './core/memory-git.js';
7
8
  import { buildMachineProfile, saveMachineProfile, loadMachineProfile, renderMachineProfileSummary } from './core/machine-profile.js';
8
9
  import { buildAgentInventory, saveAgentInventory, loadAgentInventory, renderAgentInventorySummary } from './core/agent-inventory.js';
@@ -22,6 +23,7 @@ import { runCompleteStep } from './commands/complete-step.js';
22
23
  import { runUpdateHandoff } from './commands/update-handoff.js';
23
24
  import { runInstruction } from './commands/instruction.js';
24
25
  import { runListAgents } from './commands/list-agents.js';
26
+ import { runSurfaceTaskResource } from './commands/surface-task-resource.js';
25
27
  import { runListInstructions } from './commands/list-instructions.js';
26
28
  import { runDoctor } from './commands/doctor.js';
27
29
  import { runRebuild } from './commands/rebuild.js';
@@ -169,7 +171,7 @@ program
169
171
  // --- machine-profile ---
170
172
  program
171
173
  .command('machine-profile')
172
- .description('Detect and persist machine capabilities (OS, shells, git users, SSH keys, toolchains, WSL)')
174
+ .description('Detect and persist machine capabilities (OS, shells, git users, SSH keys, toolchains, WSL, AI surfaces)')
173
175
  .option('--refresh', 'Force regeneration even if profile exists')
174
176
  .option('--json', 'Output as JSON')
175
177
  .action(async (options) => {
@@ -402,6 +404,28 @@ program
402
404
  .action((id, options) => {
403
405
  runUpdatePlan(id, { ...options, actualEffort: options.actualEffort });
404
406
  });
407
+ // --- surface-task ---
408
+ program
409
+ .command('surface-task <subcommand> [args...]')
410
+ .description('Manage queued tasks for desktop AI surfaces such as ChatGPT Desktop or Claude Desktop')
411
+ .option('--json', 'Output as JSON for list')
412
+ .option('--all', 'Include completed, cancelled, and failed tasks in list')
413
+ .option('--status <status>', 'Status filter/update: queued, in_progress, completed, cancelled, failed')
414
+ .option('--target <surface>', 'Target surface, e.g. chatgpt, claude, gemini')
415
+ .option('--kind <kind>', 'Task kind: visual_asset, draft, summary, analysis, research, custom')
416
+ .option('--instructions <text>', 'Detailed instructions for the target surface')
417
+ .option('--output <paths...>', 'Expected output paths')
418
+ .option('--result <text>', 'Optional result note when updating a task')
419
+ .option('--tag <tags...>', 'Tags for this task')
420
+ .option('--path <paths...>', 'Related file paths')
421
+ .option('--agent <agent>', 'Author agent name')
422
+ .option('--agent-id <agentId>', 'Author agent id')
423
+ .action((subcommand, args, options) => {
424
+ runSurfaceTaskResource(subcommand, args, {
425
+ ...options,
426
+ agentId: options.agentId,
427
+ });
428
+ });
405
429
  // --- delete-plan ---
406
430
  program
407
431
  .command('delete-plan <id>')
@@ -439,6 +463,17 @@ program
439
463
  .action((options) => {
440
464
  runVersion(options);
441
465
  });
466
+ // --- uninstall ---
467
+ import { runUninstall } from './commands/uninstall.js';
468
+ program
469
+ .command('uninstall')
470
+ .description('Remove brainclaw from a project and/or machine')
471
+ .option('--project', 'Remove brainclaw from the current project (.brainclaw/, agent files, configs)')
472
+ .option('--machine', 'Remove brainclaw global config (~/.brainclaw/)')
473
+ .option('-y, --yes', 'Skip confirmation prompts')
474
+ .action(async (options) => {
475
+ await runUninstall(options);
476
+ });
442
477
  // --- rebuild ---
443
478
  program
444
479
  .command('rebuild')
@@ -915,6 +950,25 @@ program
915
950
  .action((options) => {
916
951
  runExport(options);
917
952
  });
953
+ program
954
+ .command('reconcile')
955
+ .description('Refresh machine and workspace bootstrap state after updates or onboarding on complex installs')
956
+ .option('--json', 'Output as JSON')
957
+ .option('--dry-run', 'Preview the reconciliation plan without writing machine or bootstrap state')
958
+ .option('--apply-bootstrap', 'Apply bootstrap suggestions across all selected stores after refresh')
959
+ .option('-y, --yes', 'Skip confirmation prompts for multi-store bootstrap apply')
960
+ .option('--skip-machine-profile', 'Skip machine-profile refresh')
961
+ .option('--skip-agent-inventory', 'Skip agent-inventory refresh')
962
+ .action(async (options) => {
963
+ await runReconcile({
964
+ json: options.json,
965
+ dryRun: options.dryRun,
966
+ applyBootstrap: options.applyBootstrap,
967
+ yes: options.yes,
968
+ skipMachineProfile: options.skipMachineProfile,
969
+ skipAgentInventory: options.skipAgentInventory,
970
+ });
971
+ });
918
972
  // --- hooks ---
919
973
  program
920
974
  .command('hooks')
@@ -0,0 +1,18 @@
1
+ import path from 'node:path';
2
+ import { buildClaudeDesktopExtension, renderClaudeDesktopExtensionSummary, } from '../core/claude-desktop-extension.js';
3
+ export function runClaudeDesktopExtension(options = {}) {
4
+ const cwd = options.cwd ?? process.cwd();
5
+ const result = buildClaudeDesktopExtension({
6
+ cwd,
7
+ workspaceDir: options.workspace ? path.resolve(cwd, options.workspace) : undefined,
8
+ outputFile: options.output ? path.resolve(cwd, options.output) : undefined,
9
+ projectRoot: options.projectRoot ? path.resolve(cwd, options.projectRoot) : undefined,
10
+ pack: options.pack,
11
+ });
12
+ if (options.json) {
13
+ console.log(JSON.stringify(result, null, 2));
14
+ return;
15
+ }
16
+ console.log(renderClaudeDesktopExtensionSummary(result));
17
+ }
18
+ //# sourceMappingURL=claude-desktop-extension.js.map
@@ -3,6 +3,7 @@ import { buildContext, renderContextMarkdown, renderContextPromptTemplate } from
3
3
  import { writeContextMarker } from '../core/freshness.js';
4
4
  import { nowISO } from '../core/ids.js';
5
5
  import { logger } from '../core/logger.js';
6
+ import { resolveContextStoreCwd } from '../core/store-resolution.js';
6
7
  export function runContext(options = {}) {
7
8
  const cwd = options.cwd ?? process.cwd();
8
9
  if (!memoryExists(cwd)) {
@@ -17,6 +18,7 @@ export function runContext(options = {}) {
17
18
  }
18
19
  return;
19
20
  }
21
+ const contextCwd = resolveContextStoreCwd(cwd, options.for);
20
22
  const result = buildContext({
21
23
  target: options.for,
22
24
  project: options.project,
@@ -43,7 +45,7 @@ export function runContext(options = {}) {
43
45
  else {
44
46
  console.log(renderContextMarkdown(result, options.explain));
45
47
  }
46
- writeLastContextMarker(result, options, cwd);
48
+ writeLastContextMarker(result, options, contextCwd);
47
49
  }
48
50
  function writeLastContextMarker(result, options, cwd) {
49
51
  try {
@@ -25,6 +25,7 @@ import { assessBrainclawVersion } from '../core/brainclaw-version.js';
25
25
  import { resolveStoreChain } from '../core/store-resolution.js';
26
26
  import { resolveCrossProjectLinks, detectCrossProjectCycles } from '../core/cross-project.js';
27
27
  import { auditLocalAgentWorkspaceFiles, ensureGitignoreEntries } from '../core/agent-files.js';
28
+ import { summarizeWorkspaceProjects } from '../core/workspace-projects.js';
28
29
  const BACKLOG_KEYWORDS = /\b(TODO|NEXT|backlog|next[\s-]step|action[\s-]item|prochaine?s?\s+étapes?|à\s+faire)\b/i;
29
30
  function hasBacklogPatterns(text) {
30
31
  const lines = text.split(/\r?\n/);
@@ -138,14 +139,19 @@ export function runDoctor(options = {}) {
138
139
  });
139
140
  }
140
141
  }
141
- if (config.project_mode === 'multi-project' && (config.projects?.known.length ?? 0) === 0) {
142
+ const workspaceProjects = summarizeWorkspaceProjects(options.cwd ?? process.cwd(), config);
143
+ if (config.project_mode === 'multi-project' && workspaceProjects.effective_project_count === 0) {
142
144
  checks.push({
143
145
  name: 'project_mode',
144
146
  status: 'warn',
145
- message: 'project_mode is multi-project but no project namespaces are configured yet.',
147
+ message: config.projects?.strategy === 'folder'
148
+ ? 'project_mode is multi-project with folder strategy but no child projects were resolved from config, registry, or nested stores yet.'
149
+ : 'project_mode is multi-project but no project namespaces are configured yet.',
146
150
  });
147
151
  if (!options.json) {
148
- console.warn('⚠ project_mode is multi-project but no project namespaces are configured yet.');
152
+ console.warn(config.projects?.strategy === 'folder'
153
+ ? '⚠ project_mode is multi-project with folder strategy but no child projects were resolved from config, registry, or nested stores yet.'
154
+ : '⚠ project_mode is multi-project but no project namespaces are configured yet.');
149
155
  }
150
156
  hasIssues = true;
151
157
  }
@@ -153,10 +159,11 @@ export function runDoctor(options = {}) {
153
159
  checks.push({
154
160
  name: 'project_mode',
155
161
  status: 'ok',
156
- message: `project_mode=${config.project_mode}, strategy=${config.projects?.strategy ?? 'manual'}, known_projects=${config.projects?.known.length ?? 0}`,
162
+ message: `project_mode=${config.project_mode}, strategy=${config.projects?.strategy ?? 'manual'}, configured_projects=${workspaceProjects.configured_projects.length}, effective_projects=${workspaceProjects.effective_project_count}`,
163
+ details: workspaceProjects,
157
164
  });
158
165
  if (!options.json) {
159
- console.log(`✔ project mode: ${config.project_mode} (${config.projects?.strategy ?? 'manual'})`);
166
+ console.log(`✔ project mode: ${config.project_mode} (${config.projects?.strategy ?? 'manual'}), effective projects=${workspaceProjects.effective_project_count}`);
160
167
  }
161
168
  }
162
169
  try {
@@ -8,6 +8,9 @@ import { resolveInstructions, loadInstructions } from '../core/instructions.js';
8
8
  import { detectAiAgent } from '../core/ai-agent-detection.js';
9
9
  import { resolveExportTarget, resolveExportTargetByFormat, writeExportFile, buildHygieneSection, describeAutoConfigWrite, writeExportCompanionFiles, collectExportGitignoreEntries, ensureGitignoreEntries, } from '../core/agent-files.js';
10
10
  import { logger } from '../core/logger.js';
11
+ import { getAgentCapabilityProfile } from '../core/agent-capability.js';
12
+ import { renderBrainclawSection } from '../core/instruction-templates.js';
13
+ import { getInstalledBrainclawVersion } from '../core/brainclaw-version.js';
11
14
  export function runExport(options) {
12
15
  const cwd = options.cwd ?? process.cwd();
13
16
  if (!memoryExists(cwd)) {
@@ -125,7 +128,28 @@ function declareAgentIntegrationFromTarget(cwd, agentName, declarationSource) {
125
128
  saveConfig(config, cwd);
126
129
  }
127
130
  }
131
+ function formatToAgentName(format) {
132
+ const map = {
133
+ 'claude-md': 'claude-code',
134
+ 'cursor-rules': 'cursor',
135
+ 'copilot-instructions': 'github-copilot',
136
+ 'agents-md': 'codex',
137
+ 'gemini-md': 'antigravity',
138
+ 'windsurf': 'windsurf',
139
+ 'cline': 'cline',
140
+ 'roo': 'roo',
141
+ 'continue': 'continue',
142
+ };
143
+ return map[format];
144
+ }
128
145
  function generateExport(format, options, cwd) {
146
+ const agentName = formatToAgentName(format);
147
+ if (agentName) {
148
+ const adaptive = generateAdaptiveExport(agentName, options, cwd);
149
+ if (adaptive)
150
+ return adaptive;
151
+ }
152
+ // Fallback to legacy generators for unknown formats
129
153
  switch (format) {
130
154
  case 'copilot-instructions': return generateCopilotInstructions(options, cwd);
131
155
  case 'cursor-rules': return generateCursorRules(options, cwd);
@@ -140,6 +164,26 @@ function generateExport(format, options, cwd) {
140
164
  throw new Error(`Unknown export format: ${format}`);
141
165
  }
142
166
  }
167
+ /**
168
+ * Generate export content using adaptive templates when a capability profile
169
+ * exists for the agent, falling back to the legacy per-format generators.
170
+ */
171
+ function generateAdaptiveExport(agentName, options, cwd) {
172
+ const profile = getAgentCapabilityProfile(agentName);
173
+ if (!profile)
174
+ return undefined;
175
+ const state = loadState(cwd);
176
+ const instructions = getInstructionText(options, cwd);
177
+ const config = loadConfig(cwd);
178
+ const result = renderBrainclawSection({
179
+ profile,
180
+ state,
181
+ projectName: config.project_name,
182
+ brainclawVersion: getInstalledBrainclawVersion(),
183
+ resolvedInstructions: instructions,
184
+ });
185
+ return result.content;
186
+ }
143
187
  function getInstructionText(options, cwd) {
144
188
  try {
145
189
  const all = loadInstructions(cwd);
@@ -14,17 +14,19 @@ import { renderBootstrapSummary, runBootstrapProfile } from '../core/bootstrap.j
14
14
  import { isAgentIntegrationName, upsertAgentIntegrationDeclaration } from '../core/agent-integrations.js';
15
15
  import { describeAutoConfigWrite, ensureAgentFiles, ensureGitignoreEntries, writeDetectedAgentAutoConfig } from '../core/agent-files.js';
16
16
  import { detectAiAgent, detectWslEnvironment } from '../core/ai-agent-detection.js';
17
- import { hasCompletedSetup } from '../core/setup-state.js';
17
+ import { buildAiSurfaceInventory, renderAiSurfaceUsageHints } from '../core/ai-surface-inventory.js';
18
+ import { ensureUserStore, hasCompletedSetup } from '../core/setup-state.js';
18
19
  import { writeDetectedAgentExport } from './export.js';
19
20
  import { writeDetectedAgentHooks } from './hooks.js';
20
21
  export async function runInit(options = {}) {
21
22
  const cwd = options.cwd ?? process.cwd();
22
23
  const containingMemoryStore = resolveContainingMemoryStore(cwd);
23
- const skipSetupRequirement = options.skipSetupRequirement === true || process.env.BRAINCLAW_SKIP_SETUP_REQUIREMENT === '1';
24
- if (!skipSetupRequirement && !hasCompletedSetup()) {
25
- console.error('Error: global brainclaw setup has not been completed on this machine.');
26
- console.error('Run `brainclaw setup` first, then retry `brainclaw init` from your project root.');
27
- process.exit(1);
24
+ // Auto-create user store if absent (replaces the old "setup required" guard).
25
+ // The skipSetupRequirement flag and BRAINCLAW_SKIP_SETUP_REQUIREMENT env var
26
+ // are kept for backward compatibility but are now effectively no-ops —
27
+ // init always ensures the user store exists before proceeding.
28
+ if (!hasCompletedSetup()) {
29
+ ensureUserStore();
28
30
  }
29
31
  if (containingMemoryStore) {
30
32
  console.error(`Error: cannot run \`brainclaw init\` from inside an existing project memory store (${containingMemoryStore}).`);
@@ -178,6 +180,20 @@ export async function runInit(options = {}) {
178
180
  if (detectedExport) {
179
181
  console.log(`\u2714 Agent instructions written to ${detectedExport.relativePath} (${detectedExport.created ? 'created' : 'updated'})`);
180
182
  }
183
+ const visibleSurfaces = buildAiSurfaceInventory().filter((surface) => surface.status !== 'not_detected');
184
+ if (visibleSurfaces.length > 0) {
185
+ console.log('✔ Other AI work surfaces detected on this machine:');
186
+ for (const surface of visibleSurfaces) {
187
+ console.log(` - ${surface.display_name} [${surface.surface_kind}, ${surface.status}]`);
188
+ }
189
+ const usageHints = renderAiSurfaceUsageHints(visibleSurfaces);
190
+ if (usageHints.length > 0) {
191
+ console.log(' Suggested uses:');
192
+ for (const line of usageHints) {
193
+ console.log(` ${line}`);
194
+ }
195
+ }
196
+ }
181
197
  for (const hook of detectedHooks) {
182
198
  console.log(`\u2714 Session hook written to ${hook.relativePath} (${hook.created ? 'created' : 'updated'})`);
183
199
  }
@@ -0,0 +1,39 @@
1
+ import { memoryExists } from '../core/io.js';
2
+ import { listAiSurfaceTasks } from '../core/ai-surface-tasks.js';
3
+ export function runListSurfaceTasks(options = {}) {
4
+ if (!memoryExists(options.cwd)) {
5
+ console.error('Error: .brainclaw/ not found. Run `brainclaw init` first.');
6
+ process.exit(1);
7
+ }
8
+ let tasks = listAiSurfaceTasks(options.cwd);
9
+ if (!options.all) {
10
+ tasks = tasks.filter((task) => task.status === 'queued' || task.status === 'in_progress');
11
+ }
12
+ if (options.status) {
13
+ tasks = tasks.filter((task) => task.status === options.status);
14
+ }
15
+ if (options.target) {
16
+ const target = options.target.toLowerCase();
17
+ tasks = tasks.filter((task) => task.target_surface.toLowerCase() === target);
18
+ }
19
+ if (options.json) {
20
+ console.log(JSON.stringify(tasks, null, 2));
21
+ return;
22
+ }
23
+ if (tasks.length === 0) {
24
+ console.log('No surface tasks.');
25
+ return;
26
+ }
27
+ console.log(`${tasks.length} surface task(s):`);
28
+ console.log('');
29
+ for (const task of tasks) {
30
+ console.log(` [${task.id}] ${task.title} (${task.status}, target ${task.target_surface}, kind ${task.kind})`);
31
+ if (task.requested_outputs.length > 0) {
32
+ console.log(` outputs: ${task.requested_outputs.join(', ')}`);
33
+ }
34
+ if (task.result_note) {
35
+ console.log(` result: ${task.result_note}`);
36
+ }
37
+ }
38
+ }
39
+ //# sourceMappingURL=list-surface-tasks.js.map
@@ -30,6 +30,8 @@ import { buildEstimationReport } from './estimation-report.js';
30
30
  import { detectAiAgent } from '../core/ai-agent-detection.js';
31
31
  import { checkGitPresence, scanGitRepos, parseRoots, parseRepoSelection, parseAgentSelection, runGlobalInstall, initReposAndConfigureAgents, readSetupState, ALL_KNOWN_AGENTS, } from './setup.js';
32
32
  import { resolveTargetStore, resolveStoreChain } from '../core/store-resolution.js';
33
+ import { probeForQuickSetup, buildQuickSetupProbeResponse, buildOnboardingPreview } from '../core/setup-flow.js';
34
+ import { ensureUserStore } from '../core/setup-state.js';
33
35
  import { readUnseenEvents, buildNotificationSummary } from '../core/event-log.js';
34
36
  import { BootstrapInterviewAnswerSchema } from '../core/schema.js';
35
37
  export const SCHEMA_VERSION = '0.6.0';
@@ -246,14 +248,17 @@ export const MCP_READ_TOOLS = [
246
248
  const MCP_WRITE_TOOLS = [
247
249
  {
248
250
  name: 'bclaw_setup',
249
- description: 'Interactive onboarding wizard global agent install + multi-repo brainclaw init. Use the resume pattern: call without step to start, then pass step+choice to advance through each stage.',
251
+ description: 'Interactive onboarding wizard. Two modes: (1) Quick mode (default): probes the current repo and asks project type + topology, then inits. (2) Batch mode: scan root directories and init multiple repos. Call without step to start brainclaw auto-detects the best mode.',
250
252
  inputSchema: {
251
253
  type: 'object',
252
254
  properties: {
253
- step: { type: 'string', description: 'Current step to resume: "project_roots", "repo_selection", or "agent_selection". Omit to start from the beginning.' },
254
- choice: { type: 'string', description: 'User choice for the current step (e.g. path list, "all", "detected", or comma-separated numbers).' },
255
- roots: { type: 'string', description: 'Comma-separated root paths (required from step "repo_selection" onward to re-scan).' },
256
- repo_selection: { type: 'string', description: 'Repo selection choice from previous step (required for "agent_selection" step).' },
255
+ step: { type: 'string', description: 'Resume step: "quick_init" (quick mode), or "project_roots"/"repo_selection"/"agent_selection" (batch mode). Omit to start.' },
256
+ choice: { type: 'string', description: 'User choice for the current step.' },
257
+ project_type: { type: 'string', description: 'Quick mode: "standalone", "workspace", or "linked".' },
258
+ topology: { type: 'string', description: 'Quick mode: "embedded" (shared via git) or "sidecar" (local only).' },
259
+ roots: { type: 'string', description: 'Batch mode: comma-separated root paths.' },
260
+ repo_selection: { type: 'string', description: 'Batch mode: repo selection from previous step.' },
261
+ mode: { type: 'string', description: 'Force "quick" or "batch" mode. Default: auto-detect.' },
257
262
  },
258
263
  },
259
264
  },
@@ -1112,6 +1117,16 @@ export function handleMcpReadToolCall(name, args = {}, context = {}) {
1112
1117
  const text = args.interview
1113
1118
  ? renderBootstrapInterview(result, audience)
1114
1119
  : renderBootstrapSummary(result);
1120
+ // Extract top-level suggested questions for conversational bootstrap (step 11)
1121
+ const suggestedQuestions = result.importPlan.interview?.questions?.map((q) => ({
1122
+ id: q.id,
1123
+ prompt: q.prompt,
1124
+ rationale: q.rationale,
1125
+ priority: q.priority,
1126
+ })) ?? [];
1127
+ // Separate auto-imports (high confidence) from proposals (need discussion)
1128
+ const autoImports = result.importPlan.suggestions.filter((s) => s.confidence === 'high');
1129
+ const proposals = result.importPlan.suggestions.filter((s) => s.confidence !== 'high');
1115
1130
  return {
1116
1131
  content: [{ type: 'text', text }],
1117
1132
  structuredContent: {
@@ -1127,6 +1142,9 @@ export function handleMcpReadToolCall(name, args = {}, context = {}) {
1127
1142
  seed_count: result.profile.seed_count,
1128
1143
  seeds: result.seeds,
1129
1144
  import_plan: result.importPlan,
1145
+ auto_imports: autoImports,
1146
+ proposals,
1147
+ suggested_questions: suggestedQuestions,
1130
1148
  last_application: result.lastApplication,
1131
1149
  reused_profile: result.reusedProfile,
1132
1150
  },
@@ -1571,15 +1589,78 @@ export async function executeMcpToolCall(payload) {
1571
1589
  const choice = args.choice ?? '';
1572
1590
  const rootsArg = args.roots;
1573
1591
  const repoSelectionArg = args.repo_selection;
1592
+ const modeArg = args.mode;
1574
1593
  const env = process.env;
1575
1594
  if (!checkGitPresence()) {
1576
1595
  return { response: toolResponse({ content: [{ type: 'text', text: 'Git is not installed or not found in PATH. Install git from https://git-scm.com before running brainclaw setup.' }], structuredContent: { error: 'git_not_found' } }, true) };
1577
1596
  }
1597
+ // ─── Quick mode: probe current repo ──────────────────────────────
1578
1598
  if (!step) {
1599
+ // Auto-detect mode: if we're in a git repo, use quick mode unless batch is forced
1600
+ const forceBatch = modeArg === 'batch';
1601
+ if (!forceBatch) {
1602
+ const probe = probeForQuickSetup(cwd);
1603
+ if (probe.isGitRepo || probe.alreadyInitialized) {
1604
+ const response = buildQuickSetupProbeResponse(probe);
1605
+ return { response: toolResponse({ content: [{ type: 'text', text: response.text }], structuredContent: response.structured }) };
1606
+ }
1607
+ }
1608
+ // Fall through to batch mode
1579
1609
  const existingState = readSetupState(env);
1580
1610
  const alreadyRun = existingState ? `Setup was previously run on ${new Date(existingState.completed_at).toLocaleDateString()}. You can re-run it.` : undefined;
1581
1611
  return { response: toolResponse({ content: [{ type: 'text', text: [alreadyRun, "Where are the user's project directories? Please ask the user to provide one or more root paths where their git repositories are located (e.g. ~/Projects, C:\\Users\\user\\code)."].filter(Boolean).join('\n\n') }], structuredContent: { pending_question: 'project_roots', prompt: 'Please ask the user: "Where are your projects? Enter one or more root directories (comma-separated):"', ...(alreadyRun ? { already_run: alreadyRun } : {}) } }) };
1582
1612
  }
1613
+ // ─── Quick mode step: init with choices ──────────────────────────
1614
+ if (step === 'quick_init') {
1615
+ const projectType = args.project_type ?? 'standalone';
1616
+ const topology = args.topology ?? 'embedded';
1617
+ // Ensure user store exists
1618
+ ensureUserStore(env);
1619
+ // Map choices to init options
1620
+ const projectMode = projectType === 'workspace' ? 'multi-project' : 'auto';
1621
+ const topologyMode = topology === 'sidecar' ? 'sidecar' : 'embedded';
1622
+ // Run init
1623
+ try {
1624
+ const { runInit } = await import('./init.js');
1625
+ await runInit({
1626
+ yes: true,
1627
+ cwd,
1628
+ skipAgentBootstrap: false,
1629
+ projectMode,
1630
+ topology: topologyMode,
1631
+ });
1632
+ }
1633
+ catch (err) {
1634
+ return { response: toolResponse({ content: [{ type: 'text', text: `Init failed: ${err instanceof Error ? err.message : String(err)}` }], structuredContent: { error: 'init_failed', details: err instanceof Error ? err.message : String(err) } }, true) };
1635
+ }
1636
+ // Detect agent and report
1637
+ const detected = detectAiAgent(env);
1638
+ const summary = [
1639
+ `✔ Initialized ${cwd.split(/[\\/]/).pop() ?? cwd} (${projectType}, ${topology})`,
1640
+ ];
1641
+ if (detected) {
1642
+ summary.push(`✔ Agent detected: ${detected.name}`);
1643
+ }
1644
+ summary.push('✔ Reload your agent session to activate brainclaw MCP tools.');
1645
+ // Check if bootstrap is available and generate preview
1646
+ const probe = probeForQuickSetup(cwd);
1647
+ const bootstrapAvailable = probe.hasContent;
1648
+ const preview = buildOnboardingPreview(cwd);
1649
+ return {
1650
+ response: toolResponse({
1651
+ content: [{ type: 'text', text: summary.join('\n') + (bootstrapAvailable ? '\n\nThe repo has existing content. Run bclaw_bootstrap to extract initial project context.' : '') + '\n\n' + preview }],
1652
+ structuredContent: {
1653
+ setup_complete: true,
1654
+ project_type: projectType,
1655
+ topology,
1656
+ detected_agent: detected?.name ?? null,
1657
+ bootstrap_available: bootstrapAvailable,
1658
+ preview,
1659
+ summary,
1660
+ },
1661
+ }),
1662
+ };
1663
+ }
1583
1664
  if (step === 'project_roots') {
1584
1665
  const roots = parseRoots(choice, env);
1585
1666
  if (roots.length === 0) {