brainclaw 0.19.2
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/LICENSE +74 -0
- package/README.md +226 -0
- package/dist/cli.js +1037 -0
- package/dist/commands/accept.js +149 -0
- package/dist/commands/adapter-openclaw-import.js +75 -0
- package/dist/commands/add-step.js +35 -0
- package/dist/commands/agent-board.js +106 -0
- package/dist/commands/audit.js +35 -0
- package/dist/commands/bootstrap.js +34 -0
- package/dist/commands/capability.js +104 -0
- package/dist/commands/changes.js +112 -0
- package/dist/commands/check-constraints.js +63 -0
- package/dist/commands/claim-resource.js +54 -0
- package/dist/commands/claim.js +92 -0
- package/dist/commands/complete-step.js +34 -0
- package/dist/commands/constraint.js +44 -0
- package/dist/commands/context-diff.js +32 -0
- package/dist/commands/context.js +63 -0
- package/dist/commands/decision.js +45 -0
- package/dist/commands/delete-plan.js +20 -0
- package/dist/commands/diff.js +99 -0
- package/dist/commands/doctor.js +1275 -0
- package/dist/commands/enable-agent.js +63 -0
- package/dist/commands/env.js +46 -0
- package/dist/commands/estimation-report.js +167 -0
- package/dist/commands/explore.js +47 -0
- package/dist/commands/export.js +381 -0
- package/dist/commands/handoff.js +63 -0
- package/dist/commands/history.js +22 -0
- package/dist/commands/hooks.js +123 -0
- package/dist/commands/init.js +356 -0
- package/dist/commands/install-hooks.js +115 -0
- package/dist/commands/instruction.js +56 -0
- package/dist/commands/list-agents.js +44 -0
- package/dist/commands/list-claims.js +45 -0
- package/dist/commands/list-instructions.js +50 -0
- package/dist/commands/list-plans.js +48 -0
- package/dist/commands/mcp-worker.js +12 -0
- package/dist/commands/mcp.js +2272 -0
- package/dist/commands/memory.js +283 -0
- package/dist/commands/metrics.js +175 -0
- package/dist/commands/plan-resource.js +62 -0
- package/dist/commands/plan.js +76 -0
- package/dist/commands/prune-candidates.js +36 -0
- package/dist/commands/prune.js +48 -0
- package/dist/commands/pull.js +25 -0
- package/dist/commands/push.js +28 -0
- package/dist/commands/rebuild.js +14 -0
- package/dist/commands/reflect-runtime-note.js +74 -0
- package/dist/commands/reflect.js +286 -0
- package/dist/commands/register-agent.js +29 -0
- package/dist/commands/reject.js +52 -0
- package/dist/commands/release-claim.js +41 -0
- package/dist/commands/release-claims.js +67 -0
- package/dist/commands/review.js +242 -0
- package/dist/commands/rollback.js +156 -0
- package/dist/commands/runtime-note.js +144 -0
- package/dist/commands/runtime-status.js +49 -0
- package/dist/commands/search.js +36 -0
- package/dist/commands/session-end.js +187 -0
- package/dist/commands/session-start.js +147 -0
- package/dist/commands/set-trust.js +92 -0
- package/dist/commands/setup.js +446 -0
- package/dist/commands/show-candidate.js +31 -0
- package/dist/commands/star-candidate.js +28 -0
- package/dist/commands/status.js +133 -0
- package/dist/commands/sync.js +159 -0
- package/dist/commands/tool.js +126 -0
- package/dist/commands/trap.js +74 -0
- package/dist/commands/update-handoff.js +23 -0
- package/dist/commands/update-plan.js +37 -0
- package/dist/commands/upgrade.js +382 -0
- package/dist/commands/use-candidate.js +35 -0
- package/dist/commands/version.js +96 -0
- package/dist/commands/watch.js +215 -0
- package/dist/commands/whoami.js +104 -0
- package/dist/core/agent-context.js +340 -0
- package/dist/core/agent-files.js +874 -0
- package/dist/core/agent-integrations.js +135 -0
- package/dist/core/agent-inventory.js +401 -0
- package/dist/core/agent-registry.js +420 -0
- package/dist/core/ai-agent-detection.js +140 -0
- package/dist/core/audit.js +85 -0
- package/dist/core/bootstrap.js +658 -0
- package/dist/core/brainclaw-version.js +433 -0
- package/dist/core/candidates.js +137 -0
- package/dist/core/circuit-breaker.js +118 -0
- package/dist/core/claims.js +72 -0
- package/dist/core/config.js +86 -0
- package/dist/core/context-diff.js +122 -0
- package/dist/core/context.js +1212 -0
- package/dist/core/contradictions.js +270 -0
- package/dist/core/coordination.js +86 -0
- package/dist/core/cross-project.js +99 -0
- package/dist/core/duplicates.js +72 -0
- package/dist/core/event-log.js +152 -0
- package/dist/core/events.js +56 -0
- package/dist/core/execution-context.js +204 -0
- package/dist/core/freshness.js +87 -0
- package/dist/core/global-registry.js +182 -0
- package/dist/core/host.js +10 -0
- package/dist/core/identity.js +151 -0
- package/dist/core/ids.js +56 -0
- package/dist/core/input-validation.js +81 -0
- package/dist/core/instructions.js +117 -0
- package/dist/core/io.js +191 -0
- package/dist/core/json-store.js +63 -0
- package/dist/core/lifecycle.js +45 -0
- package/dist/core/lock.js +129 -0
- package/dist/core/logger.js +49 -0
- package/dist/core/machine-profile.js +332 -0
- package/dist/core/markdown.js +120 -0
- package/dist/core/memory-git.js +133 -0
- package/dist/core/migration.js +247 -0
- package/dist/core/project-registry.js +64 -0
- package/dist/core/reflection-safety.js +21 -0
- package/dist/core/repo-analysis.js +133 -0
- package/dist/core/reputation.js +409 -0
- package/dist/core/runtime.js +134 -0
- package/dist/core/schema.js +580 -0
- package/dist/core/search.js +115 -0
- package/dist/core/security.js +66 -0
- package/dist/core/setup-state.js +50 -0
- package/dist/core/state.js +83 -0
- package/dist/core/store-resolution.js +119 -0
- package/dist/core/sync-remote.js +83 -0
- package/dist/core/traps.js +86 -0
- package/package.json +60 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,1037 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { runInit } from './commands/init.js';
|
|
4
|
+
import { runSetup } from './commands/setup.js';
|
|
5
|
+
import { runUpgrade } from './commands/upgrade.js';
|
|
6
|
+
import { getMemoryLog, rollbackMemory, hasMemoryRepo } from './core/memory-git.js';
|
|
7
|
+
import { buildMachineProfile, saveMachineProfile, loadMachineProfile, renderMachineProfileSummary } from './core/machine-profile.js';
|
|
8
|
+
import { buildAgentInventory, saveAgentInventory, loadAgentInventory, renderAgentInventorySummary } from './core/agent-inventory.js';
|
|
9
|
+
import { scanAndRegister, scanProject, upsertProject, loadGlobalRegistry, renderGlobalRegistrySummary } from './core/global-registry.js';
|
|
10
|
+
import { runStatus } from './commands/status.js';
|
|
11
|
+
import { runDecision } from './commands/decision.js';
|
|
12
|
+
import { runConstraint } from './commands/constraint.js';
|
|
13
|
+
import { runTrap } from './commands/trap.js';
|
|
14
|
+
import { runHandoff } from './commands/handoff.js';
|
|
15
|
+
import { runListPlans } from './commands/list-plans.js';
|
|
16
|
+
import { runUpdatePlan } from './commands/update-plan.js';
|
|
17
|
+
import { runDeletePlan } from './commands/delete-plan.js';
|
|
18
|
+
import { runPlanResource } from './commands/plan-resource.js';
|
|
19
|
+
import { runAddStep } from './commands/add-step.js';
|
|
20
|
+
import { runEstimationReport } from './commands/estimation-report.js';
|
|
21
|
+
import { runCompleteStep } from './commands/complete-step.js';
|
|
22
|
+
import { runUpdateHandoff } from './commands/update-handoff.js';
|
|
23
|
+
import { runInstruction } from './commands/instruction.js';
|
|
24
|
+
import { runListAgents } from './commands/list-agents.js';
|
|
25
|
+
import { runListInstructions } from './commands/list-instructions.js';
|
|
26
|
+
import { runDoctor } from './commands/doctor.js';
|
|
27
|
+
import { runRebuild } from './commands/rebuild.js';
|
|
28
|
+
import { runReflect } from './commands/reflect.js';
|
|
29
|
+
import { runReflectRuntimeNote } from './commands/reflect-runtime-note.js';
|
|
30
|
+
import { runReview } from './commands/review.js';
|
|
31
|
+
import { runShowCandidate } from './commands/show-candidate.js';
|
|
32
|
+
import { runStarCandidate } from './commands/star-candidate.js';
|
|
33
|
+
import { runUseCandidate } from './commands/use-candidate.js';
|
|
34
|
+
import { runAccept } from './commands/accept.js';
|
|
35
|
+
import { runReject } from './commands/reject.js';
|
|
36
|
+
import { runPruneCandidates } from './commands/prune-candidates.js';
|
|
37
|
+
import { runListClaims } from './commands/list-claims.js';
|
|
38
|
+
import { runReleaseClaim } from './commands/release-claim.js';
|
|
39
|
+
import { runClaimResource } from './commands/claim-resource.js';
|
|
40
|
+
import { runMemoryCommand } from './commands/memory.js';
|
|
41
|
+
import { runReleaseClaims } from './commands/release-claims.js';
|
|
42
|
+
import { runAgentBoard } from './commands/agent-board.js';
|
|
43
|
+
import { runRuntimeNote } from './commands/runtime-note.js';
|
|
44
|
+
import { runRuntimeStatus } from './commands/runtime-status.js';
|
|
45
|
+
import { runSync } from './commands/sync.js';
|
|
46
|
+
import { runContext } from './commands/context.js';
|
|
47
|
+
import { runBootstrap } from './commands/bootstrap.js';
|
|
48
|
+
import { runEnv } from './commands/env.js';
|
|
49
|
+
import { runAdapterOpenclawImport } from './commands/adapter-openclaw-import.js';
|
|
50
|
+
import { runInstallHooks } from './commands/install-hooks.js';
|
|
51
|
+
import { runCheckConstraints } from './commands/check-constraints.js';
|
|
52
|
+
import { runRegisterAgent } from './commands/register-agent.js';
|
|
53
|
+
import { runEnableAgent } from './commands/enable-agent.js';
|
|
54
|
+
import { runVersion } from './commands/version.js';
|
|
55
|
+
import { runDiff } from './commands/changes.js';
|
|
56
|
+
import { runPrune } from './commands/prune.js';
|
|
57
|
+
import { runMcp } from './commands/mcp.js';
|
|
58
|
+
import { runSetTrust } from './commands/set-trust.js';
|
|
59
|
+
import { runSessionStart } from './commands/session-start.js';
|
|
60
|
+
import { runSessionEnd } from './commands/session-end.js';
|
|
61
|
+
import { runWhoami } from './commands/whoami.js';
|
|
62
|
+
import { runSearch } from './commands/search.js';
|
|
63
|
+
import { runExport } from './commands/export.js';
|
|
64
|
+
import { runHooks } from './commands/hooks.js';
|
|
65
|
+
import { runWatch } from './commands/watch.js';
|
|
66
|
+
import { runMetrics } from './commands/metrics.js';
|
|
67
|
+
import { runRollback } from './commands/rollback.js';
|
|
68
|
+
import { runPull } from './commands/pull.js';
|
|
69
|
+
import { runPush } from './commands/push.js';
|
|
70
|
+
import { runAuditCommand } from './commands/audit.js';
|
|
71
|
+
import { runHistory } from './commands/history.js';
|
|
72
|
+
import { runContextDiff } from './commands/context-diff.js';
|
|
73
|
+
import { runCapability } from './commands/capability.js';
|
|
74
|
+
import { runTool } from './commands/tool.js';
|
|
75
|
+
import { runExplore } from './commands/explore.js';
|
|
76
|
+
import { getInstalledBrainclawVersion } from './core/brainclaw-version.js';
|
|
77
|
+
import { cleanOrphanFiles, memoryDir } from './core/io.js';
|
|
78
|
+
import { initLogLevel, logger } from './core/logger.js';
|
|
79
|
+
const program = new Command();
|
|
80
|
+
function collect(value, previous) {
|
|
81
|
+
return [...previous, value];
|
|
82
|
+
}
|
|
83
|
+
program
|
|
84
|
+
.name('brainclaw')
|
|
85
|
+
.description('Shared project memory for humans and coding agents.')
|
|
86
|
+
.version(getInstalledBrainclawVersion())
|
|
87
|
+
.option('--verbose', 'Show info-level log messages on stderr')
|
|
88
|
+
.option('--debug', 'Show debug-level log messages on stderr')
|
|
89
|
+
.hook('preAction', (_thisCommand, actionCommand) => {
|
|
90
|
+
const root = actionCommand.optsWithGlobals();
|
|
91
|
+
initLogLevel({ verbose: root.verbose, debug: root.debug });
|
|
92
|
+
const removed = cleanOrphanFiles(memoryDir());
|
|
93
|
+
if (removed > 0) {
|
|
94
|
+
logger.info(`Cleaned ${removed} orphan lock/tmp file(s) in ${memoryDir()}`);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
// --- init ---
|
|
98
|
+
program
|
|
99
|
+
.command('init')
|
|
100
|
+
.description('Initialize project memory in .brainclaw/ storage directory')
|
|
101
|
+
.option('-y, --yes', 'Skip interactive wizard and use defaults')
|
|
102
|
+
.option('--force', 'Overwrite existing project memory directory')
|
|
103
|
+
.option('--compact', 'Enable compact markdown mode')
|
|
104
|
+
.option('--topology <mode>', 'Topology mode: embedded, sidecar, local-only')
|
|
105
|
+
.option('--project-mode <mode>', 'Project mode: single-project, multi-project, auto')
|
|
106
|
+
.option('--project-strategy <strategy>', 'Project strategy for multi-project mode: manual, folder')
|
|
107
|
+
.option('--no-analyze-repo', 'Skip repository analysis when suggesting a project mode')
|
|
108
|
+
.option('--scan', 'Scan subdirectories for service boundaries and suggest init targets')
|
|
109
|
+
.action(async (options) => {
|
|
110
|
+
await runInit(options);
|
|
111
|
+
});
|
|
112
|
+
// --- setup ---
|
|
113
|
+
program
|
|
114
|
+
.command('setup')
|
|
115
|
+
.description('Interactive onboarding wizard — global agent install + multi-repo init')
|
|
116
|
+
.option('--roots <paths>', 'Comma-separated root directories to scan (skips interactive prompt)')
|
|
117
|
+
.option('--agents <agents>', 'Agents to configure: all, detected, or comma-separated names')
|
|
118
|
+
.option('--repos <mode>', 'Repo selection: all, current, or comma-separated numbers')
|
|
119
|
+
.option('-y, --yes', 'Accept all defaults non-interactively')
|
|
120
|
+
.action(async (options) => {
|
|
121
|
+
await runSetup(options);
|
|
122
|
+
});
|
|
123
|
+
// --- memory-log ---
|
|
124
|
+
program
|
|
125
|
+
.command('memory-log')
|
|
126
|
+
.description('Show recent memory change history (from internal git repo)')
|
|
127
|
+
.option('-n, --limit <count>', 'Number of entries to show', '20')
|
|
128
|
+
.action((options) => {
|
|
129
|
+
const entries = getMemoryLog(parseInt(options.limit, 10));
|
|
130
|
+
if (entries.length === 0) {
|
|
131
|
+
console.log('No memory history available. Run `brainclaw init --force` to enable memory versioning.');
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
console.log(`Memory history (${entries.length} entries):\n`);
|
|
135
|
+
for (const entry of entries) {
|
|
136
|
+
console.log(` ${entry}`);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
// --- memory-rollback ---
|
|
140
|
+
program
|
|
141
|
+
.command('memory-rollback <ref>')
|
|
142
|
+
.description('Rollback entire memory to a previous git snapshot (use memory-log to find refs)')
|
|
143
|
+
.action((ref) => {
|
|
144
|
+
if (!hasMemoryRepo()) {
|
|
145
|
+
console.error('Error: no memory git repo. Run `brainclaw init --force` to enable.');
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
const success = rollbackMemory(ref);
|
|
149
|
+
if (success) {
|
|
150
|
+
console.log(`✔ Memory rolled back to ${ref}`);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
console.error(`Error: failed to rollback to '${ref}'. Check memory-log for valid refs.`);
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
// --- upgrade ---
|
|
158
|
+
program
|
|
159
|
+
.command('upgrade')
|
|
160
|
+
.description('Upgrade project memory structure and refresh managed workspace agent files without losing data')
|
|
161
|
+
.option('--json', 'Output as JSON')
|
|
162
|
+
.option('--dry-run', 'Show what would be done without making changes')
|
|
163
|
+
.action((options) => {
|
|
164
|
+
runUpgrade({
|
|
165
|
+
json: options.json,
|
|
166
|
+
dryRun: options.dryRun,
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
// --- machine-profile ---
|
|
170
|
+
program
|
|
171
|
+
.command('machine-profile')
|
|
172
|
+
.description('Detect and persist machine capabilities (OS, shells, git users, SSH keys, toolchains, WSL)')
|
|
173
|
+
.option('--refresh', 'Force regeneration even if profile exists')
|
|
174
|
+
.option('--json', 'Output as JSON')
|
|
175
|
+
.action(async (options) => {
|
|
176
|
+
const existing = loadMachineProfile();
|
|
177
|
+
if (existing && !options.refresh) {
|
|
178
|
+
if (options.json) {
|
|
179
|
+
console.log(JSON.stringify(existing, null, 2));
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
console.log(renderMachineProfileSummary(existing));
|
|
183
|
+
console.log('\nUse --refresh to regenerate.');
|
|
184
|
+
}
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
console.log('Detecting machine capabilities...');
|
|
188
|
+
const profile = buildMachineProfile();
|
|
189
|
+
const filePath = saveMachineProfile(profile);
|
|
190
|
+
if (options.json) {
|
|
191
|
+
console.log(JSON.stringify(profile, null, 2));
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
console.log(renderMachineProfileSummary(profile));
|
|
195
|
+
console.log(`\n✔ Profile saved to ${filePath}`);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
// --- agent-inventory ---
|
|
199
|
+
program
|
|
200
|
+
.command('agent-inventory')
|
|
201
|
+
.description('Detect all installed AI coding agents and their capabilities')
|
|
202
|
+
.option('--refresh', 'Force regeneration even if inventory exists')
|
|
203
|
+
.option('--json', 'Output as JSON')
|
|
204
|
+
.action(async (options) => {
|
|
205
|
+
const existing = loadAgentInventory();
|
|
206
|
+
if (existing && !options.refresh) {
|
|
207
|
+
if (options.json) {
|
|
208
|
+
console.log(JSON.stringify(existing, null, 2));
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
console.log(renderAgentInventorySummary(existing));
|
|
212
|
+
console.log('\nUse --refresh to regenerate.');
|
|
213
|
+
}
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
console.log('Detecting installed agents...');
|
|
217
|
+
const inventory = buildAgentInventory();
|
|
218
|
+
const filePath = saveAgentInventory(inventory);
|
|
219
|
+
if (options.json) {
|
|
220
|
+
console.log(JSON.stringify(inventory, null, 2));
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
console.log(renderAgentInventorySummary(inventory));
|
|
224
|
+
console.log(`\n✔ Inventory saved to ${filePath}`);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
// --- projects ---
|
|
228
|
+
program
|
|
229
|
+
.command('projects')
|
|
230
|
+
.description('List all brainclaw-initialized projects on this machine')
|
|
231
|
+
.option('--scan <roots>', 'Comma-separated directories to scan for projects')
|
|
232
|
+
.option('--register', 'Register the current project in the global registry')
|
|
233
|
+
.option('--json', 'Output as JSON')
|
|
234
|
+
.action(async (options) => {
|
|
235
|
+
if (options.register) {
|
|
236
|
+
const entry = scanProject(process.cwd());
|
|
237
|
+
if (!entry) {
|
|
238
|
+
console.error('No brainclaw project found in current directory. Run brainclaw init first.');
|
|
239
|
+
process.exit(1);
|
|
240
|
+
}
|
|
241
|
+
upsertProject(entry);
|
|
242
|
+
console.log(`✔ Registered ${entry.project_name} (${entry.project_id})`);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (options.scan) {
|
|
246
|
+
const roots = options.scan.split(',').map((r) => r.trim());
|
|
247
|
+
console.log(`Scanning ${roots.join(', ')}...`);
|
|
248
|
+
const registry = scanAndRegister(roots);
|
|
249
|
+
if (options.json) {
|
|
250
|
+
console.log(JSON.stringify(registry, null, 2));
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
console.log(renderGlobalRegistrySummary(registry));
|
|
254
|
+
}
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
// Default: show existing registry
|
|
258
|
+
const registry = loadGlobalRegistry();
|
|
259
|
+
if (!registry || registry.projects.length === 0) {
|
|
260
|
+
console.log('No projects registered. Use --scan <roots> or --register to add projects.');
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
if (options.json) {
|
|
264
|
+
console.log(JSON.stringify(registry, null, 2));
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
console.log(renderGlobalRegistrySummary(registry));
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
// --- decision ---
|
|
271
|
+
program
|
|
272
|
+
.command('decision <text>')
|
|
273
|
+
.description('Add a recent decision')
|
|
274
|
+
.option('--outcome <outcome>', 'Outcome: approved, rejected, deferred, pending')
|
|
275
|
+
.option('--tag <tags...>', 'Tags for this decision')
|
|
276
|
+
.option('--path <paths...>', 'Related file paths')
|
|
277
|
+
.option('--author <author>', 'Author name')
|
|
278
|
+
.option('--plan <id>', 'Optional linked plan item ID')
|
|
279
|
+
.option('--store <target>', 'Target store level: local (default), repo, workspace, user')
|
|
280
|
+
.action((text, options) => {
|
|
281
|
+
runDecision(text, options);
|
|
282
|
+
});
|
|
283
|
+
// --- constraint ---
|
|
284
|
+
program
|
|
285
|
+
.command('constraint <text>')
|
|
286
|
+
.description('Add an active constraint')
|
|
287
|
+
.option('--category <category>', 'Category: architecture, performance, security, reliability, compatibility, process, other')
|
|
288
|
+
.option('--tag <tags...>', 'Tags for this constraint')
|
|
289
|
+
.option('--path <paths...>', 'Related file paths')
|
|
290
|
+
.option('--author <author>', 'Author name')
|
|
291
|
+
.option('--store <target>', 'Target store level: local (default), repo, workspace, user')
|
|
292
|
+
.action((text, options) => {
|
|
293
|
+
runConstraint(text, options);
|
|
294
|
+
});
|
|
295
|
+
// --- trap ---
|
|
296
|
+
program
|
|
297
|
+
.command('trap <text>')
|
|
298
|
+
.description('Add a known trap')
|
|
299
|
+
.option('--status <status>', 'Status: active, resolved, expired', 'active')
|
|
300
|
+
.option('--severity <severity>', 'Severity: low, medium, high', 'medium')
|
|
301
|
+
.option('--visibility <visibility>', 'Visibility: shared, machine, private', 'shared')
|
|
302
|
+
.option('--host <host>', 'Optional host identifier override for machine/private traps')
|
|
303
|
+
.option('--tag <tags...>', 'Tags for this trap')
|
|
304
|
+
.option('--path <paths...>', 'Related file paths')
|
|
305
|
+
.option('--author <author>', 'Author name')
|
|
306
|
+
.option('--ttl <duration>', 'Time-to-live: 30m, 2h, 7d (trap auto-expires after this duration)')
|
|
307
|
+
.option('--store <target>', 'Target store level: local (default), repo, workspace, user')
|
|
308
|
+
.action((text, options) => {
|
|
309
|
+
runTrap(text, options);
|
|
310
|
+
});
|
|
311
|
+
// --- handoff ---
|
|
312
|
+
program
|
|
313
|
+
.command('handoff <text>')
|
|
314
|
+
.description('Create a handoff')
|
|
315
|
+
.requiredOption('--from <from>', 'Source of the handoff')
|
|
316
|
+
.requiredOption('--to <to>', 'Destination of the handoff')
|
|
317
|
+
.option('--tag <tags...>', 'Tags for this handoff')
|
|
318
|
+
.option('--path <paths...>', 'Related file paths')
|
|
319
|
+
.option('--project <project>', 'Optional project namespace')
|
|
320
|
+
.option('--plan <id>', 'Optional linked plan item ID')
|
|
321
|
+
.option('--author <author>', 'Author name')
|
|
322
|
+
.option('--capture-diff', 'Capture current git diff into the handoff snapshot')
|
|
323
|
+
.action((text, options) => {
|
|
324
|
+
runHandoff(text, options);
|
|
325
|
+
});
|
|
326
|
+
// --- status ---
|
|
327
|
+
program
|
|
328
|
+
.command('status')
|
|
329
|
+
.description('Show project memory status')
|
|
330
|
+
.option('--json', 'Output as JSON')
|
|
331
|
+
.option('--markdown', 'Output as Markdown')
|
|
332
|
+
.action((options) => {
|
|
333
|
+
runStatus(options);
|
|
334
|
+
});
|
|
335
|
+
// --- plan ---
|
|
336
|
+
program
|
|
337
|
+
.command('plan <subcommand> [args...]')
|
|
338
|
+
.description('Manage shared plan items (create, list, update, delete)')
|
|
339
|
+
.option('--json', 'Output as JSON for list')
|
|
340
|
+
.option('--all', 'Include done and dropped plan items in list')
|
|
341
|
+
.option('--type <type>', 'Plan type or filter: feat, fix, chore, spike, doc')
|
|
342
|
+
.option('--status <status>', 'Status filter/update: todo, in_progress, blocked, done, dropped')
|
|
343
|
+
.option('--priority <priority>', 'Priority: low, medium, high', 'medium')
|
|
344
|
+
.option('--assignee <assignee>', 'Assignee for this plan item')
|
|
345
|
+
.option('--project <project>', 'Optional project namespace')
|
|
346
|
+
.option('--tag <tags...>', 'Tags for this plan item')
|
|
347
|
+
.option('--path <paths...>', 'Related file paths')
|
|
348
|
+
.option('--depends-on <ids...>', 'Dependency IDs for this plan item')
|
|
349
|
+
.option('--author <author>', 'Author name')
|
|
350
|
+
.option('--estimate <minutes>', 'Estimated effort in minutes (positive integer, e.g. --estimate 30)')
|
|
351
|
+
.option('--actual-effort <effort>', 'Actual effort spent (e.g. "20min", "1h30m")')
|
|
352
|
+
.option('--store <target>', 'Target store level: local (default), repo, workspace, user')
|
|
353
|
+
.action((subcommand, args, options) => {
|
|
354
|
+
runPlanResource(subcommand, args, { ...options, actualEffort: options.actualEffort });
|
|
355
|
+
});
|
|
356
|
+
// --- list-plans ---
|
|
357
|
+
program
|
|
358
|
+
.command('list-plans')
|
|
359
|
+
.description('List shared plan items')
|
|
360
|
+
.option('--json', 'Output as JSON')
|
|
361
|
+
.option('--status <status>', 'Status: todo, in_progress, blocked, done, dropped')
|
|
362
|
+
.option('--type <type>', 'Filter by type: feat, fix, chore, spike, doc')
|
|
363
|
+
.option('--assignee <assignee>', 'Filter by assignee')
|
|
364
|
+
.option('--project <project>', 'Filter by project namespace')
|
|
365
|
+
.option('--all', 'Include done and dropped plan items')
|
|
366
|
+
.action((options) => {
|
|
367
|
+
runListPlans(options);
|
|
368
|
+
});
|
|
369
|
+
// --- add-step ---
|
|
370
|
+
program
|
|
371
|
+
.command('add-step <planId> <text>')
|
|
372
|
+
.description('Add an optional step to a plan item')
|
|
373
|
+
.option('--assign <assignee>', 'Assign this step to an agent or person')
|
|
374
|
+
.action((planId, text, options) => {
|
|
375
|
+
runAddStep(planId, text, { assignee: options.assign });
|
|
376
|
+
});
|
|
377
|
+
// --- complete-step ---
|
|
378
|
+
program
|
|
379
|
+
.command('complete-step <planId> <stepId>')
|
|
380
|
+
.description('Mark a plan step as done')
|
|
381
|
+
.action((planId, stepId) => {
|
|
382
|
+
runCompleteStep(planId, stepId);
|
|
383
|
+
});
|
|
384
|
+
// --- estimation-report ---
|
|
385
|
+
program
|
|
386
|
+
.command('estimation-report')
|
|
387
|
+
.description('Show estimation accuracy report for completed plans')
|
|
388
|
+
.option('--agent <name>', 'Filter by agent/author name')
|
|
389
|
+
.option('--json', 'Output as JSON')
|
|
390
|
+
.action((options) => {
|
|
391
|
+
runEstimationReport(options);
|
|
392
|
+
});
|
|
393
|
+
// --- update-plan ---
|
|
394
|
+
program
|
|
395
|
+
.command('update-plan <id>')
|
|
396
|
+
.description('Update a shared plan item')
|
|
397
|
+
.option('--status <status>', 'Status: todo, in_progress, blocked, done, dropped')
|
|
398
|
+
.option('--assignee <assignee>', 'Assign a user or agent to this plan item')
|
|
399
|
+
.option('--project <project>', 'Set or change project namespace')
|
|
400
|
+
.option('--priority <priority>', 'Priority: low, medium, high')
|
|
401
|
+
.option('--actual-effort <effort>', 'Actual effort spent (e.g. "20min", "1h30m")')
|
|
402
|
+
.action((id, options) => {
|
|
403
|
+
runUpdatePlan(id, { ...options, actualEffort: options.actualEffort });
|
|
404
|
+
});
|
|
405
|
+
// --- delete-plan ---
|
|
406
|
+
program
|
|
407
|
+
.command('delete-plan <id>')
|
|
408
|
+
.description('Delete a shared plan item')
|
|
409
|
+
.action((id) => {
|
|
410
|
+
runDeletePlan(id);
|
|
411
|
+
});
|
|
412
|
+
// --- update-handoff ---
|
|
413
|
+
program
|
|
414
|
+
.command('update-handoff <id>')
|
|
415
|
+
.description('Update the status of a handoff')
|
|
416
|
+
.option('--status <status>', 'Status: open, accepted, closed')
|
|
417
|
+
.option('--to <agent>', 'Change the receiving agent')
|
|
418
|
+
.action((id, options) => {
|
|
419
|
+
runUpdateHandoff(id, options);
|
|
420
|
+
});
|
|
421
|
+
// --- doctor ---
|
|
422
|
+
program
|
|
423
|
+
.command('doctor')
|
|
424
|
+
.description('Check memory health and security')
|
|
425
|
+
.option('--json', 'Output as JSON dashboard')
|
|
426
|
+
.option('--migration-check', 'Report versioned documents that need schema migration')
|
|
427
|
+
.option('--fix-agent-ignore', 'Add missing .gitignore entries for generated local Brainclaw agent files')
|
|
428
|
+
.action((options) => {
|
|
429
|
+
runDoctor(options);
|
|
430
|
+
});
|
|
431
|
+
// --- version ---
|
|
432
|
+
program
|
|
433
|
+
.command('version')
|
|
434
|
+
.description('Show the installed brainclaw version and the project version policy')
|
|
435
|
+
.option('--check', 'Check the configured installable update source')
|
|
436
|
+
.option('--publish-local', 'Create/update the local installable .releases channel via npm pack')
|
|
437
|
+
.option('--release-notes <text>', 'Attach release notes to the generated local-pack manifest')
|
|
438
|
+
.option('--json', 'Output as JSON')
|
|
439
|
+
.action((options) => {
|
|
440
|
+
runVersion(options);
|
|
441
|
+
});
|
|
442
|
+
// --- rebuild ---
|
|
443
|
+
program
|
|
444
|
+
.command('rebuild')
|
|
445
|
+
.description('Rebuild project.md from canonical memory state')
|
|
446
|
+
.action(() => {
|
|
447
|
+
runRebuild();
|
|
448
|
+
});
|
|
449
|
+
// --- reflect ---
|
|
450
|
+
program
|
|
451
|
+
.command('reflect [text]')
|
|
452
|
+
.description('Create a memory candidate for review')
|
|
453
|
+
.option('--type <type>', 'Type: constraint, decision, trap, handoff')
|
|
454
|
+
.option('--batch <file>', 'Import runtime events from JSON file')
|
|
455
|
+
.option('--session <id>', 'Import runtime events by session id from .brainclaw/runtime/')
|
|
456
|
+
.option('--tag <tags...>', 'Tags')
|
|
457
|
+
.option('--author <author>', 'Author name')
|
|
458
|
+
.option('--source <source>', 'Source context (e.g. agent name)')
|
|
459
|
+
.option('--severity <severity>', 'Severity for traps: low, medium, high')
|
|
460
|
+
.option('--from <from>', 'Handoff source')
|
|
461
|
+
.option('--to <to>', 'Handoff destination')
|
|
462
|
+
.option('--path <paths...>', 'Related file paths')
|
|
463
|
+
.action((text, options) => {
|
|
464
|
+
runReflect(text, options);
|
|
465
|
+
});
|
|
466
|
+
// --- reflect-runtime-note ---
|
|
467
|
+
program
|
|
468
|
+
.command('reflect-runtime-note <id> [text]')
|
|
469
|
+
.description('Turn a visible runtime note into a shared review candidate')
|
|
470
|
+
.option('--type <type>', 'Type: constraint, decision, trap, handoff')
|
|
471
|
+
.option('--host <host>', 'Look up machine-local runtime note for a specific host')
|
|
472
|
+
.option('--all-hosts', 'Look up runtime notes across all hosts')
|
|
473
|
+
.option('--suggest', 'Show candidate type suggestions before or instead of creation')
|
|
474
|
+
.option('--json', 'Output suggestions as JSON when used with --suggest or without --type')
|
|
475
|
+
.option('--tag <tags...>', 'Additional tags to merge with the runtime note tags')
|
|
476
|
+
.option('--author <author>', 'Author name for the candidate')
|
|
477
|
+
.option('--source <source>', 'Source context for the candidate')
|
|
478
|
+
.option('--severity <severity>', 'Severity for traps: low, medium, high')
|
|
479
|
+
.option('--from <from>', 'Handoff source')
|
|
480
|
+
.option('--to <to>', 'Handoff destination')
|
|
481
|
+
.option('--path <paths...>', 'Related file paths')
|
|
482
|
+
.action((id, text, options) => {
|
|
483
|
+
runReflectRuntimeNote(id, text, options);
|
|
484
|
+
});
|
|
485
|
+
// --- context ---
|
|
486
|
+
program
|
|
487
|
+
.command('context')
|
|
488
|
+
.description('Generate compact context for agents')
|
|
489
|
+
.option('--for <target>', 'Task/path/goal to prioritize')
|
|
490
|
+
.option('--project <project>', 'Explicit project namespace for layered instructions')
|
|
491
|
+
.option('--agent <agent>', 'Agent name for agent-layer instructions')
|
|
492
|
+
.option('--host <host>', 'Include machine-local runtime notes for a specific host')
|
|
493
|
+
.option('--all-hosts', 'Include machine-local runtime notes from all hosts')
|
|
494
|
+
.option('--profile <profile>', 'Profile: dev, openclaw, ops, research')
|
|
495
|
+
.option('--include-pending', 'Include pending candidates')
|
|
496
|
+
.option('--max-items <count>', 'Limit number of items', parseInt)
|
|
497
|
+
.option('--max-chars <count>', 'Approximate output budget for selected item content', parseInt)
|
|
498
|
+
.option('--digest', 'Include a short deterministic digest ahead of the detailed context')
|
|
499
|
+
.option('--since-session <id>', 'Include a compact memory diff since the given session started')
|
|
500
|
+
.option('--no-bootstrap', 'Disable brownfield bootstrap fallback when canonical memory is sparse')
|
|
501
|
+
.option('--refresh-bootstrap', 'Refresh brownfield bootstrap profile before building context')
|
|
502
|
+
.option('--template', 'Output prompt-ready context template')
|
|
503
|
+
.option('--compact-template', 'Use compact template format (default for openclaw profile)')
|
|
504
|
+
.option('--explain', 'Show ranking reasons in human-readable output')
|
|
505
|
+
.option('--json', 'Output as JSON')
|
|
506
|
+
.action((options) => {
|
|
507
|
+
runContext(options);
|
|
508
|
+
});
|
|
509
|
+
// --- bootstrap ---
|
|
510
|
+
program
|
|
511
|
+
.command('bootstrap')
|
|
512
|
+
.description('Derive brownfield bootstrap signals from the current repository')
|
|
513
|
+
.option('--for <target>', 'Target path or scope to tailor the bootstrap')
|
|
514
|
+
.option('--json', 'Output as JSON')
|
|
515
|
+
.option('--refresh', 'Force a fresh bootstrap scan instead of reusing the current profile')
|
|
516
|
+
.action((options) => {
|
|
517
|
+
runBootstrap(options);
|
|
518
|
+
});
|
|
519
|
+
// --- env ---
|
|
520
|
+
program
|
|
521
|
+
.command('env')
|
|
522
|
+
.description('Show the local execution context and optionally detected agent tooling')
|
|
523
|
+
.option('--json', 'Output as JSON')
|
|
524
|
+
.option('--agent-tooling', 'Include AGENTS.md, local skills, and local MCP inventory')
|
|
525
|
+
.action((options) => {
|
|
526
|
+
runEnv({ ...options, agentTooling: options.agentTooling });
|
|
527
|
+
});
|
|
528
|
+
// --- memory ---
|
|
529
|
+
program
|
|
530
|
+
.command('memory <subcommand> [args...]')
|
|
531
|
+
.description('Manage canonical memory items (create, list, update, delete)')
|
|
532
|
+
.option('--json', 'Output as JSON for list')
|
|
533
|
+
.option('--type <type>', 'Memory type/filter: decision, constraint, trap, handoff')
|
|
534
|
+
.option('--text <text>', 'Replacement text for memory update')
|
|
535
|
+
.option('--tag <tags...>', 'Tags')
|
|
536
|
+
.option('--path <paths...>', 'Related file paths')
|
|
537
|
+
.option('--author <author>', 'Author name')
|
|
538
|
+
.option('--outcome <outcome>', 'Decision outcome: approved, rejected, deferred, pending')
|
|
539
|
+
.option('--category <category>', 'Constraint category: architecture, performance, security, reliability, compatibility, process, other')
|
|
540
|
+
.option('--status <status>', 'Constraint, trap, or handoff status')
|
|
541
|
+
.option('--severity <severity>', 'Trap severity: low, medium, high')
|
|
542
|
+
.option('--project <project>', 'Optional project namespace')
|
|
543
|
+
.option('--plan <id>', 'Optional linked plan item ID')
|
|
544
|
+
.option('--from <from>', 'Handoff source')
|
|
545
|
+
.option('--to <to>', 'Handoff destination')
|
|
546
|
+
.option('--visibility <visibility>', 'Trap visibility: shared, machine, private', 'shared')
|
|
547
|
+
.option('--host <host>', 'Optional host identifier override for machine/private traps')
|
|
548
|
+
.option('--ttl <duration>', 'Time-to-live: 30m, 2h, 7d')
|
|
549
|
+
.option('--store <target>', 'Target store level: local (default), repo, workspace, user')
|
|
550
|
+
.action((subcommand, args, options) => {
|
|
551
|
+
runMemoryCommand(subcommand, args, options);
|
|
552
|
+
});
|
|
553
|
+
// --- instruction ---
|
|
554
|
+
program
|
|
555
|
+
.command('instruction <text>')
|
|
556
|
+
.description('Add a layered shared instruction')
|
|
557
|
+
.option('--layer <layer>', 'Instruction layer: global, project, agent', 'global')
|
|
558
|
+
.option('--project <project>', 'Project namespace when --layer project is used')
|
|
559
|
+
.option('--agent <agent>', 'Agent name when --layer agent is used')
|
|
560
|
+
.option('--tag <tags...>', 'Tags for this instruction')
|
|
561
|
+
.option('--author <author>', 'Author name')
|
|
562
|
+
.option('--supersedes <id>', 'Supersede an older instruction entry')
|
|
563
|
+
.option('--store <target>', 'Target store level: local (default), repo, workspace, user')
|
|
564
|
+
.action((text, options) => {
|
|
565
|
+
runInstruction(text, options);
|
|
566
|
+
});
|
|
567
|
+
// --- list-instructions ---
|
|
568
|
+
program
|
|
569
|
+
.command('list-instructions')
|
|
570
|
+
.description('List raw or resolved shared instructions')
|
|
571
|
+
.option('--json', 'Output as JSON')
|
|
572
|
+
.option('--layer <layer>', 'Filter by layer: global, project, agent')
|
|
573
|
+
.option('--project <project>', 'Project namespace filter')
|
|
574
|
+
.option('--agent <agent>', 'Agent name filter')
|
|
575
|
+
.option('--active', 'Only show active entries')
|
|
576
|
+
.option('--resolved', 'Resolve effective instructions for the given scope')
|
|
577
|
+
.option('--for <target>', 'Infer project namespace from target path when strategy=folder')
|
|
578
|
+
.action((options) => {
|
|
579
|
+
runListInstructions(options);
|
|
580
|
+
});
|
|
581
|
+
// --- register-agent ---
|
|
582
|
+
program
|
|
583
|
+
.command('register-agent <name>')
|
|
584
|
+
.description('Register an agent or human identity in project memory')
|
|
585
|
+
.option('--kind <kind>', 'Identity kind: agent, human, unknown', 'unknown')
|
|
586
|
+
.option('--capability <value>', 'Declare a capability on the agent profile (repeatable)', collect, [])
|
|
587
|
+
.option('--replace-capabilities', 'Replace existing capabilities instead of merging')
|
|
588
|
+
.option('--generate-fingerprint', 'Generate or rotate a local public identity fingerprint for this agent')
|
|
589
|
+
.option('--set-current', 'Set this identity as the current agent in config')
|
|
590
|
+
.option('--curator', 'Register this agent as a curator (project owner with direct-write access)')
|
|
591
|
+
.option('--json', 'Output as JSON')
|
|
592
|
+
.action((name, options) => {
|
|
593
|
+
runRegisterAgent(name, options);
|
|
594
|
+
});
|
|
595
|
+
// --- enable-agent ---
|
|
596
|
+
program
|
|
597
|
+
.command('enable-agent <name>')
|
|
598
|
+
.description('Activate a supported coding agent on an already initialized project')
|
|
599
|
+
.option('--kind <kind>', 'Identity kind: agent, human, unknown', 'agent')
|
|
600
|
+
.option('--capability <value>', 'Declare a capability on the agent profile (repeatable)', collect, [])
|
|
601
|
+
.option('--replace-capabilities', 'Replace existing capabilities instead of merging')
|
|
602
|
+
.option('--generate-fingerprint', 'Generate or rotate a local public identity fingerprint for this agent')
|
|
603
|
+
.option('--set-current', 'Set this identity as the current agent in config')
|
|
604
|
+
.option('--json', 'Output as JSON')
|
|
605
|
+
.action((name, options) => {
|
|
606
|
+
runEnableAgent(name, options);
|
|
607
|
+
});
|
|
608
|
+
// --- list-agents ---
|
|
609
|
+
program
|
|
610
|
+
.command('list-agents')
|
|
611
|
+
.description('List registered agent identities')
|
|
612
|
+
.option('--json', 'Output as JSON')
|
|
613
|
+
.option('--with-reputation', 'Include bounded reputation summaries when available')
|
|
614
|
+
.action((options) => {
|
|
615
|
+
runListAgents(options);
|
|
616
|
+
});
|
|
617
|
+
// --- review ---
|
|
618
|
+
program
|
|
619
|
+
.command('review')
|
|
620
|
+
.description('List pending memory candidates')
|
|
621
|
+
.option('--json', 'Output as JSON')
|
|
622
|
+
.option('--type <type>', 'Filter by type')
|
|
623
|
+
.option('--prioritized', 'Sort by review priority and show SLA')
|
|
624
|
+
.option('--only-overdue', 'Show only candidates overdue review SLA')
|
|
625
|
+
.option('--assignee <assignee>', 'Filter by assignee tag (assignee:<name>)')
|
|
626
|
+
.option('--for-curator <curator>', 'Shortcut assignee filter for curator queue')
|
|
627
|
+
.option('--take <count>', 'Limit number of reviewed items', parseInt)
|
|
628
|
+
.option('--claim <curator>', 'Atomically assign selected candidates to a curator')
|
|
629
|
+
.option('--auto', 'Auto-promote candidates meeting the configured score threshold')
|
|
630
|
+
.option('--auto-by <actor>', 'Actor identity for auto-promotion (defaults to current user)')
|
|
631
|
+
.action((options) => {
|
|
632
|
+
runReview({ ...options, autoBy: options.autoBy });
|
|
633
|
+
});
|
|
634
|
+
// --- show-candidate ---
|
|
635
|
+
program
|
|
636
|
+
.command('show-candidate <id>')
|
|
637
|
+
.description('Show details of a memory candidate')
|
|
638
|
+
.option('--related', 'Show related candidates by shared tags/paths')
|
|
639
|
+
.action((id, options) => {
|
|
640
|
+
runShowCandidate(id, { related: options.related });
|
|
641
|
+
});
|
|
642
|
+
// --- star-candidate ---
|
|
643
|
+
program
|
|
644
|
+
.command('star-candidate <id>')
|
|
645
|
+
.description('Add an adoption star to a pending candidate')
|
|
646
|
+
.option('--by <actor>', 'Agent or person adding the star')
|
|
647
|
+
.action((id, options) => {
|
|
648
|
+
runStarCandidate(id, options);
|
|
649
|
+
});
|
|
650
|
+
// --- use-candidate ---
|
|
651
|
+
program
|
|
652
|
+
.command('use-candidate <id>')
|
|
653
|
+
.description('Record that a pending candidate was reused in a concrete work context')
|
|
654
|
+
.option('--by <actor>', 'Agent or person using the candidate')
|
|
655
|
+
.requiredOption('--context <context>', 'Work context where the candidate was reused')
|
|
656
|
+
.action((id, options) => {
|
|
657
|
+
runUseCandidate(id, options);
|
|
658
|
+
});
|
|
659
|
+
// --- accept ---
|
|
660
|
+
program
|
|
661
|
+
.command('accept <id>')
|
|
662
|
+
.description('Accept a candidate into canonical memory')
|
|
663
|
+
.option('--by <reviewer>', 'Reviewer identity used for governance checks')
|
|
664
|
+
.action((id, options) => {
|
|
665
|
+
runAccept(id, options.by);
|
|
666
|
+
});
|
|
667
|
+
// --- adapter-openclaw-import ---
|
|
668
|
+
program
|
|
669
|
+
.command('adapter-openclaw-import [file]')
|
|
670
|
+
.description('Import OpenClaw runtime events file as memory candidates')
|
|
671
|
+
.option('--session <id>', 'Import runtime events from a session id in .brainclaw/runtime/')
|
|
672
|
+
.option('--dry-run', 'Preview import without creating candidates')
|
|
673
|
+
.option('--source <source>', 'Source label for imported candidates', 'openclaw')
|
|
674
|
+
.option('--author <author>', 'Author for imported candidates')
|
|
675
|
+
.action((file, options) => {
|
|
676
|
+
runAdapterOpenclawImport(file, options);
|
|
677
|
+
});
|
|
678
|
+
// --- reject ---
|
|
679
|
+
program
|
|
680
|
+
.command('reject <id>')
|
|
681
|
+
.description('Reject a memory candidate')
|
|
682
|
+
.option('--by <reviewer>', 'Reviewer identity used for rejection attribution')
|
|
683
|
+
.option('--reason <reason>', 'Reason for rejection')
|
|
684
|
+
.action((id, options) => {
|
|
685
|
+
runReject(id, options.reason, options.by);
|
|
686
|
+
});
|
|
687
|
+
// --- prune-candidates ---
|
|
688
|
+
program
|
|
689
|
+
.command('prune-candidates')
|
|
690
|
+
.description('Remove old rejected candidates')
|
|
691
|
+
.option('--days <days>', 'Max age in days', parseInt)
|
|
692
|
+
.option('--dry-run', 'Preview without deleting')
|
|
693
|
+
.action((options) => {
|
|
694
|
+
runPruneCandidates(options);
|
|
695
|
+
});
|
|
696
|
+
// --- claim ---
|
|
697
|
+
program
|
|
698
|
+
.command('claim <subcommand> [args...]')
|
|
699
|
+
.description('Manage work claims (create, list, release)')
|
|
700
|
+
.option('--agent <agent>', 'Agent or person name; defaults to the configured current agent')
|
|
701
|
+
.option('--scope <scope>', 'Scope being claimed (e.g. file path, module)')
|
|
702
|
+
.option('--project <project>', 'Optional project namespace for this claim')
|
|
703
|
+
.option('--plan <id>', 'Optional linked plan item ID')
|
|
704
|
+
.option('--ttl <duration>', 'Auto-expire after duration: 30m, 2h, 8h, 1d')
|
|
705
|
+
.option('--all', 'Include released claims in list')
|
|
706
|
+
.option('--json', 'Output as JSON for list')
|
|
707
|
+
.option('--plan-status <status>', 'Optional linked plan status when releasing: todo, in_progress, blocked, done, dropped')
|
|
708
|
+
.option('--store <target>', 'Target store level: local (default), repo, workspace')
|
|
709
|
+
.action((subcommand, args, options) => {
|
|
710
|
+
runClaimResource(subcommand, args, { ...options, planStatus: options.planStatus });
|
|
711
|
+
});
|
|
712
|
+
// --- list-claims ---
|
|
713
|
+
program
|
|
714
|
+
.command('list-claims')
|
|
715
|
+
.description('List work claims')
|
|
716
|
+
.option('--json', 'Output as JSON')
|
|
717
|
+
.option('--all', 'Include released claims')
|
|
718
|
+
.option('--project <project>', 'Filter by project namespace')
|
|
719
|
+
.option('--plan <id>', 'Filter by linked plan item')
|
|
720
|
+
.option('--agent <agent>', 'Filter by agent name')
|
|
721
|
+
.action((options) => {
|
|
722
|
+
runListClaims(options);
|
|
723
|
+
});
|
|
724
|
+
// --- release-claim ---
|
|
725
|
+
program
|
|
726
|
+
.command('release-claim <id>')
|
|
727
|
+
.description('Release a work claim')
|
|
728
|
+
.option('--plan-status <status>', 'Optional linked plan status: todo, in_progress, blocked, done, dropped')
|
|
729
|
+
.action((id, options) => {
|
|
730
|
+
runReleaseClaim(id, options);
|
|
731
|
+
});
|
|
732
|
+
// --- release-claims ---
|
|
733
|
+
program
|
|
734
|
+
.command('release-claims')
|
|
735
|
+
.description('Bulk-release claims whose scope overlaps with git-changed files')
|
|
736
|
+
.option('--from-git-diff', 'Use ORIG_HEAD..HEAD diff to detect changed files (post-merge)')
|
|
737
|
+
.option('--ref1 <ref>', 'First git ref (default: ORIG_HEAD)')
|
|
738
|
+
.option('--ref2 <ref>', 'Second git ref (default: HEAD)')
|
|
739
|
+
.action((options) => {
|
|
740
|
+
runReleaseClaims({ fromGitDiff: options.fromGitDiff, ref1: options.ref1, ref2: options.ref2 });
|
|
741
|
+
});
|
|
742
|
+
// --- agent-board ---
|
|
743
|
+
program
|
|
744
|
+
.command('agent-board')
|
|
745
|
+
.description('Show a coordination board for agents, plans, claims, handoffs, and instructions')
|
|
746
|
+
.option('--agent <agent>', 'Filter by agent name')
|
|
747
|
+
.option('--project <project>', 'Filter by project namespace')
|
|
748
|
+
.option('--for <target>', 'Infer project from target path')
|
|
749
|
+
.option('--host <host>', 'Include machine-local runtime notes for a specific host')
|
|
750
|
+
.option('--all-hosts', 'Include machine-local runtime notes from all hosts')
|
|
751
|
+
.option('--json', 'Output as JSON')
|
|
752
|
+
.option('--with-reputation', 'Include bounded reputation summaries when available')
|
|
753
|
+
.option('--capabilities', 'List all registered agents with their declared capabilities')
|
|
754
|
+
.option('--suggest <query>', 'Suggest agents whose capabilities match a query string')
|
|
755
|
+
.option('--include-session-meta', 'Include session_start/session_end runtime notes (hidden by default)')
|
|
756
|
+
.action((options) => {
|
|
757
|
+
runAgentBoard(options);
|
|
758
|
+
});
|
|
759
|
+
// --- runtime-note ---
|
|
760
|
+
program
|
|
761
|
+
.command('runtime-note <text>')
|
|
762
|
+
.description('Add a runtime note for an agent')
|
|
763
|
+
.option('--agent <agent>', 'Agent name; defaults to the configured current agent')
|
|
764
|
+
.option('--project <project>', 'Optional project namespace')
|
|
765
|
+
.option('--plan <id>', 'Optional linked plan item ID')
|
|
766
|
+
.option('--visibility <visibility>', 'Visibility: shared, machine, private', 'shared')
|
|
767
|
+
.option('--host <host>', 'Optional host identifier override for machine/private runtime notes')
|
|
768
|
+
.option('--tag <tags...>', 'Tags')
|
|
769
|
+
.option('--ttl <duration>', 'Time-to-live: 30m, 2h, 7d (note auto-expires after this duration)')
|
|
770
|
+
.option('--auto-reflect', 'Attempt to turn this runtime note into durable memory immediately')
|
|
771
|
+
.action((text, options) => {
|
|
772
|
+
runRuntimeNote(text, { ...options, autoReflect: options.autoReflect });
|
|
773
|
+
});
|
|
774
|
+
// --- runtime-status ---
|
|
775
|
+
program
|
|
776
|
+
.command('runtime-status')
|
|
777
|
+
.description('Show runtime notes')
|
|
778
|
+
.option('--agent <agent>', 'Filter by agent')
|
|
779
|
+
.option('--plan <id>', 'Filter by linked plan item')
|
|
780
|
+
.option('--visibility <visibility>', 'Visibility filter: shared, machine, private, all')
|
|
781
|
+
.option('--host <host>', 'Include machine-local notes for a specific host')
|
|
782
|
+
.option('--all-hosts', 'Include machine-local notes from all hosts')
|
|
783
|
+
.option('--json', 'Output as JSON')
|
|
784
|
+
.action((options) => {
|
|
785
|
+
runRuntimeStatus(options);
|
|
786
|
+
});
|
|
787
|
+
// --- sync ---
|
|
788
|
+
program
|
|
789
|
+
.command('sync')
|
|
790
|
+
.description('Summarize memory changes and optionally commit')
|
|
791
|
+
.option('--commit', 'Create a local git commit')
|
|
792
|
+
.option('--message <message>', 'Custom commit message')
|
|
793
|
+
.option('--summary-only', 'Print summary only; skip git status and commit checks')
|
|
794
|
+
.option('--scope <scope>', 'Scope: all, state, config, project, inbox, archive, claims, runtime, runtime-local, trap-local')
|
|
795
|
+
.option('--include-machine-runtime', 'Include machine-local runtime memory in sync scope for all')
|
|
796
|
+
.option('--remote', 'Pull + push from/to remote memory repo in one step')
|
|
797
|
+
.action((options) => {
|
|
798
|
+
runSync({ ...options, remote: options.remote });
|
|
799
|
+
});
|
|
800
|
+
// --- check-constraints ---
|
|
801
|
+
program
|
|
802
|
+
.command('check-constraints')
|
|
803
|
+
.description('Check if staged files (or given files) violate active constraints')
|
|
804
|
+
.option('--staged', 'Check git staged files (git diff --cached --name-only)')
|
|
805
|
+
.option('--files <files...>', 'Explicit list of files to check')
|
|
806
|
+
.option('--json', 'Output as JSON')
|
|
807
|
+
.action((options) => {
|
|
808
|
+
runCheckConstraints({ staged: options.staged, files: options.files, json: options.json });
|
|
809
|
+
});
|
|
810
|
+
// --- install-hooks ---
|
|
811
|
+
program
|
|
812
|
+
.command('install-hooks')
|
|
813
|
+
.description('Install a Git pre-commit hook that blocks sensitive content in .brainclaw/ and checks active constraints')
|
|
814
|
+
.option('--force', 'Overwrite existing pre-commit hook')
|
|
815
|
+
.action((options) => {
|
|
816
|
+
runInstallHooks(options);
|
|
817
|
+
});
|
|
818
|
+
// --- diff ---
|
|
819
|
+
program
|
|
820
|
+
.command('diff')
|
|
821
|
+
.description('Show what changed in .brainclaw/ since a timestamp or last context read')
|
|
822
|
+
.option('--since <timestamp>', 'ISO 8601 timestamp to diff from')
|
|
823
|
+
.option('--json', 'Output as JSON')
|
|
824
|
+
.action((options) => {
|
|
825
|
+
runDiff(options);
|
|
826
|
+
});
|
|
827
|
+
// --- prune ---
|
|
828
|
+
program
|
|
829
|
+
.command('prune')
|
|
830
|
+
.description('Prune expired constraints and stale memory')
|
|
831
|
+
.option('--expired', 'Also prune expired runtime notes and traps')
|
|
832
|
+
.action((options) => {
|
|
833
|
+
runPrune(options);
|
|
834
|
+
});
|
|
835
|
+
// --- mcp ---
|
|
836
|
+
program
|
|
837
|
+
.command('mcp')
|
|
838
|
+
.description('Start the standalone MCP server over stdio')
|
|
839
|
+
.action(() => {
|
|
840
|
+
runMcp();
|
|
841
|
+
});
|
|
842
|
+
// --- set-trust ---
|
|
843
|
+
program
|
|
844
|
+
.command('set-trust <agent>')
|
|
845
|
+
.description('Set the trust level for a registered agent or manage circuit-breaker state')
|
|
846
|
+
.option('--level <level>', 'Trust level: observer, contributor, trusted, curator')
|
|
847
|
+
.option('--reset-breaker', 'Reset circuit-breaker suspension for the agent (restores auto-promote)')
|
|
848
|
+
.option('--json', 'Output as JSON')
|
|
849
|
+
.action((agent, options) => {
|
|
850
|
+
runSetTrust(agent, { level: options.level, resetBreaker: options.resetBreaker, json: options.json });
|
|
851
|
+
});
|
|
852
|
+
// --- session-start ---
|
|
853
|
+
program
|
|
854
|
+
.command('session-start')
|
|
855
|
+
.description('Start a memory session and capture initial context')
|
|
856
|
+
.option('--agent <agent>', 'Agent name (defaults to current configured agent)')
|
|
857
|
+
.option('--context <path>', 'Context target path for initial hash capture')
|
|
858
|
+
.option('--model <id>', 'Model identifier (e.g. claude-sonnet-4-6)')
|
|
859
|
+
.option('--json', 'Output as JSON')
|
|
860
|
+
.action((options) => {
|
|
861
|
+
runSessionStart(options);
|
|
862
|
+
});
|
|
863
|
+
// --- session-end ---
|
|
864
|
+
program
|
|
865
|
+
.command('session-end')
|
|
866
|
+
.description('End a memory session and optionally auto-reflect observations')
|
|
867
|
+
.option('--session <id>', 'Session ID (defaults to BRAINCLAW_SESSION_ID env var)')
|
|
868
|
+
.option('--agent <agent>', 'Agent name')
|
|
869
|
+
.option('--summary <text>', 'Session summary text')
|
|
870
|
+
.option('--auto-reflect', 'Auto-reflect session notes as pending candidates')
|
|
871
|
+
.option('--auto-release', 'Auto-release any active claims at session end')
|
|
872
|
+
.option('--reflect-handoff', 'Generate a handoff candidate from git commits since session start')
|
|
873
|
+
.option('--json', 'Output as JSON')
|
|
874
|
+
.action((options) => {
|
|
875
|
+
runSessionEnd({ ...options, autoReflect: options.autoReflect, autoRelease: options.autoRelease, reflectHandoff: options.reflectHandoff });
|
|
876
|
+
});
|
|
877
|
+
// --- whoami ---
|
|
878
|
+
program
|
|
879
|
+
.command('whoami')
|
|
880
|
+
.description('Show the current resolved agent identity and trust level')
|
|
881
|
+
.option('--json', 'Output as JSON')
|
|
882
|
+
.action((options) => {
|
|
883
|
+
runWhoami(options);
|
|
884
|
+
});
|
|
885
|
+
// --- search ---
|
|
886
|
+
program
|
|
887
|
+
.command('search <query>')
|
|
888
|
+
.description('Full-text search across project memory')
|
|
889
|
+
.option('--section <section>', 'Filter by section: constraints, decisions, traps, handoffs, plans')
|
|
890
|
+
.option('--since <timestamp>', 'ISO timestamp filter')
|
|
891
|
+
.option('--tag <tags...>', 'Filter by tags')
|
|
892
|
+
.option('--pending', 'Include pending candidates')
|
|
893
|
+
.option('--max-results <count>', 'Maximum results to return', parseInt)
|
|
894
|
+
.option('--json', 'Output as JSON')
|
|
895
|
+
.action((query, options) => {
|
|
896
|
+
runSearch(query, options);
|
|
897
|
+
});
|
|
898
|
+
// --- export ---
|
|
899
|
+
program
|
|
900
|
+
.command('export')
|
|
901
|
+
.description('Export memory as instructions for IDE/AI tools')
|
|
902
|
+
.option('--format <format>', 'Format: copilot-instructions, cursor-rules, agents-md, claude-md, gemini-md, windsurf, cline, roo, continue')
|
|
903
|
+
.option('--detect', 'Auto-detect agent environment and write to its native file')
|
|
904
|
+
.option('--write', 'Write to canonical file path instead of stdout (when --format is given); local files are gitignored by default')
|
|
905
|
+
.option('--shared', 'Keep the main exported instruction file versionable instead of auto-ignoring it (companions remain local)')
|
|
906
|
+
.option('--output <file>', 'Write to a specific file path instead of stdout')
|
|
907
|
+
.option('--project <project>', 'Project namespace filter')
|
|
908
|
+
.option('--agent <agent>', 'Agent name for agent-layer instructions')
|
|
909
|
+
.action((options) => {
|
|
910
|
+
runExport(options);
|
|
911
|
+
});
|
|
912
|
+
// --- hooks ---
|
|
913
|
+
program
|
|
914
|
+
.command('hooks')
|
|
915
|
+
.description('Write deterministic session-trigger hooks for Cursor (.cursor/rules/brainclaw-session.mdc) and Windsurf (.windsurfrules)')
|
|
916
|
+
.option('--target <target>', 'Which hooks to write: cursor, windsurf, all (default: all)')
|
|
917
|
+
.action((options) => {
|
|
918
|
+
runHooks(options);
|
|
919
|
+
});
|
|
920
|
+
// --- watch ---
|
|
921
|
+
program
|
|
922
|
+
.command('watch')
|
|
923
|
+
.description('Watch for memory changes and emit NDJSON events on stdout')
|
|
924
|
+
.option('--interval <seconds>', 'Poll interval in seconds', parseInt)
|
|
925
|
+
.option('--auto-claim', 'Auto-create advisory claims on first write to workspace files')
|
|
926
|
+
.option('--agent <name>', 'Agent name for auto-claim')
|
|
927
|
+
.action((options) => {
|
|
928
|
+
runWatch({ ...options, autoClaim: options.autoClaim });
|
|
929
|
+
});
|
|
930
|
+
// --- metrics ---
|
|
931
|
+
program
|
|
932
|
+
.command('metrics')
|
|
933
|
+
.description('Show memory health metrics dashboard')
|
|
934
|
+
.option('--json', 'Output as JSON')
|
|
935
|
+
.option('--since <timestamp>', 'Filter audit log stats from this ISO timestamp')
|
|
936
|
+
.action((options) => {
|
|
937
|
+
runMetrics(options);
|
|
938
|
+
});
|
|
939
|
+
// --- rollback ---
|
|
940
|
+
program
|
|
941
|
+
.command('rollback')
|
|
942
|
+
.description('Restore a memory item to a previous state from audit log')
|
|
943
|
+
.option('--audit-id <timestamp>', 'Audit log entry timestamp to roll back')
|
|
944
|
+
.option('--item-id <id>', 'Memory item ID to roll back (uses most recent audit entry with before-state)')
|
|
945
|
+
.option('--dry-run', 'Preview rollback without applying changes')
|
|
946
|
+
.option('--json', 'Output as JSON')
|
|
947
|
+
.action((options) => {
|
|
948
|
+
runRollback({ auditId: options.auditId, itemId: options.itemId, dryRun: options.dryRun, json: options.json });
|
|
949
|
+
});
|
|
950
|
+
// --- pull ---
|
|
951
|
+
program
|
|
952
|
+
.command('pull')
|
|
953
|
+
.description('Pull memory updates from a git remote')
|
|
954
|
+
.option('--remote <remote>', 'Remote name (defaults to origin)')
|
|
955
|
+
.option('--json', 'Output as JSON')
|
|
956
|
+
.action((options) => {
|
|
957
|
+
runPull(options);
|
|
958
|
+
});
|
|
959
|
+
// --- push ---
|
|
960
|
+
program
|
|
961
|
+
.command('push')
|
|
962
|
+
.description('Push memory updates to a git remote')
|
|
963
|
+
.option('--remote <remote>', 'Remote name (defaults to origin)')
|
|
964
|
+
.option('--message <message>', 'Custom commit message')
|
|
965
|
+
.option('--json', 'Output as JSON')
|
|
966
|
+
.action((options) => {
|
|
967
|
+
runPush(options);
|
|
968
|
+
});
|
|
969
|
+
// --- audit ---
|
|
970
|
+
program
|
|
971
|
+
.command('audit')
|
|
972
|
+
.description('View the append-only audit log of all memory mutations')
|
|
973
|
+
.option('--since <date>', 'Show entries since this ISO date')
|
|
974
|
+
.option('--actor <agent>', 'Filter by actor name or agent ID')
|
|
975
|
+
.option('--action <action>', 'Filter by action type (create, accept, reject, etc.)')
|
|
976
|
+
.option('--limit <n>', 'Show last N entries', parseInt)
|
|
977
|
+
.option('--json', 'Output as JSON')
|
|
978
|
+
.action((options) => {
|
|
979
|
+
runAuditCommand({ since: options.since, actor: options.actor, action: options.action, limit: options.limit, json: options.json });
|
|
980
|
+
});
|
|
981
|
+
// --- history ---
|
|
982
|
+
program
|
|
983
|
+
.command('history <id>')
|
|
984
|
+
.description('Show full mutation history of a memory item from the audit log')
|
|
985
|
+
.action((id) => {
|
|
986
|
+
runHistory(id);
|
|
987
|
+
});
|
|
988
|
+
// --- context-diff ---
|
|
989
|
+
program
|
|
990
|
+
.command('context-diff')
|
|
991
|
+
.description('Show what changed in memory since last context read, a session start, or a given timestamp')
|
|
992
|
+
.option('--since <date>', 'Show changes since this ISO date')
|
|
993
|
+
.option('--session <id>', 'Show changes since the start of this session')
|
|
994
|
+
.option('--json', 'Output as JSON')
|
|
995
|
+
.action((options) => {
|
|
996
|
+
runContextDiff({ since: options.since, session: options.session, json: options.json });
|
|
997
|
+
});
|
|
998
|
+
program
|
|
999
|
+
.command('capability <subcommand> [args...]')
|
|
1000
|
+
.description('Manage project capabilities (list, add, describe)')
|
|
1001
|
+
.option('--tag <tag>', 'Tag for categorization (repeatable)', (val, prev) => [...(prev || []), val])
|
|
1002
|
+
.option('--author <name>', 'Author name')
|
|
1003
|
+
.option('--store <target>', 'Store level: local (default), repo, workspace, user')
|
|
1004
|
+
.action((subcommand, args, options) => {
|
|
1005
|
+
runCapability(subcommand, args, {
|
|
1006
|
+
tag: options.tag,
|
|
1007
|
+
author: options.author,
|
|
1008
|
+
store: options.store,
|
|
1009
|
+
});
|
|
1010
|
+
});
|
|
1011
|
+
program
|
|
1012
|
+
.command('tool <subcommand> [args...]')
|
|
1013
|
+
.description('Manage project tools (list, add, describe, search)')
|
|
1014
|
+
.option('--tag <tag>', 'Tag for categorization (repeatable)', (val, prev) => [...(prev || []), val])
|
|
1015
|
+
.option('--type <type>', 'Tool type: workflow, validator, generator, utility, explorer')
|
|
1016
|
+
.option('--author <name>', 'Author name')
|
|
1017
|
+
.option('--store <target>', 'Store level: local (default), repo, workspace, user')
|
|
1018
|
+
.action((subcommand, args, options) => {
|
|
1019
|
+
runTool(subcommand, args, {
|
|
1020
|
+
tag: options.tag,
|
|
1021
|
+
type: options.type,
|
|
1022
|
+
author: options.author,
|
|
1023
|
+
store: options.store,
|
|
1024
|
+
});
|
|
1025
|
+
});
|
|
1026
|
+
program
|
|
1027
|
+
.command('explore')
|
|
1028
|
+
.description('Explore project capabilities and available tools')
|
|
1029
|
+
.option('--query <q>', 'Search for specific capability or tool')
|
|
1030
|
+
.action((options) => {
|
|
1031
|
+
runExplore({ query: options.query });
|
|
1032
|
+
});
|
|
1033
|
+
program.parseAsync(process.argv).catch((err) => {
|
|
1034
|
+
console.error(err);
|
|
1035
|
+
process.exit(1);
|
|
1036
|
+
});
|
|
1037
|
+
//# sourceMappingURL=cli.js.map
|