brainclaw 0.25.3 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +32 -2
- package/dist/commands/capability.js +21 -32
- package/dist/commands/check-events.js +36 -0
- package/dist/commands/discover.js +21 -0
- package/dist/commands/doctor.js +67 -11
- package/dist/commands/explore.js +7 -10
- package/dist/commands/hooks.js +33 -17
- package/dist/commands/mcp.js +380 -70
- package/dist/commands/migrate.js +75 -0
- package/dist/commands/tool.js +29 -39
- package/dist/core/agent-files.js +13 -0
- package/dist/core/context.js +102 -8
- package/dist/core/coordination.js +25 -0
- package/dist/core/io.js +2 -0
- package/dist/core/migration.js +3 -1
- package/dist/core/project-discovery.js +236 -0
- package/dist/core/registries.js +120 -0
- package/dist/core/schema.js +6 -1
- package/package.json +7 -1
package/dist/cli.js
CHANGED
|
@@ -81,6 +81,9 @@ import { cleanOrphanFiles, memoryDir } from './core/io.js';
|
|
|
81
81
|
import { initLogLevel, logger } from './core/logger.js';
|
|
82
82
|
import { resolveEffectiveCwd } from './core/store-resolution.js';
|
|
83
83
|
import { runSwitch } from './commands/switch.js';
|
|
84
|
+
import { runCheckEvents } from './commands/check-events.js';
|
|
85
|
+
import { runDiscover } from './commands/discover.js';
|
|
86
|
+
import { runMigrate } from './commands/migrate.js';
|
|
84
87
|
const program = new Command();
|
|
85
88
|
function collect(value, previous) {
|
|
86
89
|
return [...previous, value];
|
|
@@ -994,8 +997,8 @@ program
|
|
|
994
997
|
// --- hooks ---
|
|
995
998
|
program
|
|
996
999
|
.command('hooks')
|
|
997
|
-
.description('Write deterministic session-trigger hooks for Cursor
|
|
998
|
-
.option('--target <target>', 'Which hooks to write: cursor, windsurf, all (default: all)')
|
|
1000
|
+
.description('Write deterministic session-trigger hooks for Cursor, Windsurf, and Claude Code (PostToolUse event check)')
|
|
1001
|
+
.option('--target <target>', 'Which hooks to write: cursor, windsurf, claude-code, all (default: all)')
|
|
999
1002
|
.action((options) => {
|
|
1000
1003
|
runHooks(options);
|
|
1001
1004
|
});
|
|
@@ -1009,6 +1012,15 @@ program
|
|
|
1009
1012
|
.action((options) => {
|
|
1010
1013
|
runWatch({ ...options, autoClaim: options.autoClaim });
|
|
1011
1014
|
});
|
|
1015
|
+
// --- check-events ---
|
|
1016
|
+
program
|
|
1017
|
+
.command('check-events')
|
|
1018
|
+
.description('Show unseen events from the event bus (events.jsonl) for the current agent')
|
|
1019
|
+
.option('--agent <name>', 'Agent name for cursor lookup (default: auto-detected)')
|
|
1020
|
+
.option('--json', 'Output as JSON')
|
|
1021
|
+
.action((options) => {
|
|
1022
|
+
runCheckEvents(options);
|
|
1023
|
+
});
|
|
1012
1024
|
// --- metrics ---
|
|
1013
1025
|
program
|
|
1014
1026
|
.command('metrics')
|
|
@@ -1112,6 +1124,24 @@ program
|
|
|
1112
1124
|
.action((options) => {
|
|
1113
1125
|
runExplore({ query: options.query });
|
|
1114
1126
|
});
|
|
1127
|
+
// --- discover ---
|
|
1128
|
+
program
|
|
1129
|
+
.command('discover')
|
|
1130
|
+
.description('Scan workspace for MCP configs, instruction files, skills, hooks, and agent integrations')
|
|
1131
|
+
.option('--json', 'Output as JSON')
|
|
1132
|
+
.option('--no-save', 'Do not persist discovery profile to .brainclaw/discovery/')
|
|
1133
|
+
.action((options) => {
|
|
1134
|
+
runDiscover({ json: options.json, save: options.save });
|
|
1135
|
+
});
|
|
1136
|
+
// --- migrate ---
|
|
1137
|
+
program
|
|
1138
|
+
.command('migrate')
|
|
1139
|
+
.description('Migrate memory items between stores (e.g. promote machine-scoped items to user store)')
|
|
1140
|
+
.option('--promote-machine-items', 'Move items with scope:machine from project store to user store (~/.brainclaw/)')
|
|
1141
|
+
.option('--dry-run', 'Show what would be moved without actually moving')
|
|
1142
|
+
.action((options) => {
|
|
1143
|
+
runMigrate({ promoteMachineItems: options.promoteMachineItems, dryRun: options.dryRun });
|
|
1144
|
+
});
|
|
1115
1145
|
program
|
|
1116
1146
|
.command('switch [project]')
|
|
1117
1147
|
.description('Set the active project for subsequent commands')
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { loadState, persistState } from '../core/state.js';
|
|
2
1
|
import { resolveCurrentAgentName } from '../core/agent-registry.js';
|
|
3
2
|
import { memoryExists } from '../core/io.js';
|
|
4
|
-
import { generateIdWithLabel, nowISO } from '../core/ids.js';
|
|
5
3
|
import { loadConfig } from '../core/config.js';
|
|
6
4
|
import { scanText } from '../core/security.js';
|
|
7
5
|
import { validateCliInput } from '../core/input-validation.js';
|
|
8
6
|
import { resolveTargetStore } from '../core/store-resolution.js';
|
|
7
|
+
import { listCapabilities, createCapability } from '../core/registries.js';
|
|
9
8
|
export function runCapability(subcommand, args, options = {}) {
|
|
10
9
|
const cwd = resolveTargetStore(options.cwd ?? process.cwd(), options.store ?? 'local');
|
|
11
10
|
if (!memoryExists(cwd)) {
|
|
@@ -38,10 +37,7 @@ export function runCapability(subcommand, args, options = {}) {
|
|
|
38
37
|
}
|
|
39
38
|
}
|
|
40
39
|
function runCapabilityList(cwd) {
|
|
41
|
-
const
|
|
42
|
-
const capabilities = state.active_constraints
|
|
43
|
-
.filter((c) => c.tags.includes('capability'))
|
|
44
|
-
.map((c) => ({ id: c.id, name: c.text.split('\n')[0], tags: c.tags }));
|
|
40
|
+
const capabilities = listCapabilities(cwd);
|
|
45
41
|
if (capabilities.length === 0) {
|
|
46
42
|
console.log('No capabilities registered yet.');
|
|
47
43
|
return;
|
|
@@ -49,8 +45,8 @@ function runCapabilityList(cwd) {
|
|
|
49
45
|
console.log(`\n${capabilities.length} capability(ies):\n`);
|
|
50
46
|
capabilities.forEach((cap) => {
|
|
51
47
|
console.log(` [${cap.id}] ${cap.name}`);
|
|
52
|
-
if (cap.tags.length >
|
|
53
|
-
console.log(` tags: ${cap.tags.
|
|
48
|
+
if (cap.tags.length > 0) {
|
|
49
|
+
console.log(` tags: ${cap.tags.join(', ')}`);
|
|
54
50
|
}
|
|
55
51
|
});
|
|
56
52
|
console.log('');
|
|
@@ -66,36 +62,29 @@ function runCapabilityAdd(name, description, options, cwd) {
|
|
|
66
62
|
process.exit(1);
|
|
67
63
|
}
|
|
68
64
|
}
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
short_label,
|
|
74
|
-
text: name,
|
|
75
|
-
created_at: nowISO(),
|
|
65
|
+
const cap = createCapability({
|
|
66
|
+
name,
|
|
67
|
+
description,
|
|
68
|
+
tags: options.tag,
|
|
76
69
|
author: options.author ?? resolveCurrentAgentName(cwd),
|
|
77
|
-
|
|
78
|
-
};
|
|
79
|
-
// For now, store as decision to avoid schema migration
|
|
80
|
-
// Will migrate to separate capability storage in v0.16
|
|
81
|
-
state.recent_decisions.push(entry);
|
|
82
|
-
persistState(state, cwd);
|
|
83
|
-
console.log(`✔ Capability added: [${id}] ${name}`);
|
|
84
|
-
console.log(' (Stored in decisions for now; will move to dedicated registry in v0.16)');
|
|
70
|
+
}, cwd);
|
|
71
|
+
console.log(`✔ Capability added: [${cap.id}] ${name}`);
|
|
85
72
|
}
|
|
86
73
|
function runCapabilityDescribe(capId, cwd) {
|
|
87
|
-
const
|
|
88
|
-
const
|
|
89
|
-
if (!
|
|
74
|
+
const capabilities = listCapabilities(cwd);
|
|
75
|
+
const cap = capabilities.find((c) => c.id === capId || c.id.startsWith(capId));
|
|
76
|
+
if (!cap) {
|
|
90
77
|
console.error(`Error: capability '${capId}' not found`);
|
|
91
78
|
process.exit(1);
|
|
92
79
|
}
|
|
93
|
-
console.log(`\nCapability: ${
|
|
94
|
-
console.log(`
|
|
95
|
-
console.log(`
|
|
96
|
-
console.log(`
|
|
97
|
-
|
|
98
|
-
|
|
80
|
+
console.log(`\nCapability: ${cap.name}`);
|
|
81
|
+
console.log(`Description: ${cap.description}`);
|
|
82
|
+
console.log(`ID: ${cap.id}`);
|
|
83
|
+
console.log(`Category: ${cap.category}`);
|
|
84
|
+
console.log(`Author: ${cap.author}`);
|
|
85
|
+
console.log(`Created: ${cap.created_at}`);
|
|
86
|
+
if (cap.tags.length > 0) {
|
|
87
|
+
console.log(`Tags: ${cap.tags.join(', ')}`);
|
|
99
88
|
}
|
|
100
89
|
console.log('');
|
|
101
90
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { memoryExists } from '../core/io.js';
|
|
2
|
+
import { readUnseenEvents, buildNotificationSummary } from '../core/event-log.js';
|
|
3
|
+
import { resolveCurrentAgentName } from '../core/agent-registry.js';
|
|
4
|
+
export function runCheckEvents(options = {}) {
|
|
5
|
+
if (!memoryExists()) {
|
|
6
|
+
console.error('Error: .brainclaw/ not found. Run `brainclaw init` first.');
|
|
7
|
+
process.exit(1);
|
|
8
|
+
}
|
|
9
|
+
const agent = options.agent ?? resolveCurrentAgentName();
|
|
10
|
+
const events = readUnseenEvents(agent);
|
|
11
|
+
if (events.length === 0) {
|
|
12
|
+
if (options.json) {
|
|
13
|
+
console.log(JSON.stringify({ agent, unseen: 0 }));
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
console.log('No unseen events.');
|
|
17
|
+
}
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const summary = buildNotificationSummary(events) ?? {};
|
|
21
|
+
if (options.json) {
|
|
22
|
+
console.log(JSON.stringify({ agent, unseen: events.length, summary, events }));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
console.log(`${events.length} unseen event(s) since last read:\n`);
|
|
26
|
+
for (const [key, count] of Object.entries(summary)) {
|
|
27
|
+
console.log(` ${key}: ${count}`);
|
|
28
|
+
}
|
|
29
|
+
console.log('');
|
|
30
|
+
for (const evt of events) {
|
|
31
|
+
const id = evt.item_id ? ` [${evt.item_id.slice(0, 12)}]` : '';
|
|
32
|
+
const sum = evt.summary ? ` — ${evt.summary}` : '';
|
|
33
|
+
console.log(` ${evt.ts} ${evt.agent} ${evt.action}:${evt.item_type}${id}${sum}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=check-events.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { memoryExists } from '../core/io.js';
|
|
2
|
+
import { buildProjectDiscovery, saveDiscoveryProfile, renderDiscoverySummary, } from '../core/project-discovery.js';
|
|
3
|
+
export function runDiscover(options = {}) {
|
|
4
|
+
const cwd = options.cwd ?? process.cwd();
|
|
5
|
+
if (!memoryExists(cwd)) {
|
|
6
|
+
console.error('Error: .brainclaw/ not found. Run `brainclaw init` first.');
|
|
7
|
+
process.exit(1);
|
|
8
|
+
}
|
|
9
|
+
const profile = buildProjectDiscovery({ cwd });
|
|
10
|
+
// Save by default (non-destructive refresh)
|
|
11
|
+
if (options.save !== false) {
|
|
12
|
+
saveDiscoveryProfile(profile, cwd);
|
|
13
|
+
}
|
|
14
|
+
if (options.json) {
|
|
15
|
+
console.log(JSON.stringify(profile, null, 2));
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
console.log(renderDiscoverySummary(profile));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=discover.js.map
|
package/dist/commands/doctor.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { listAgentIdentities, resolveCurrentAgentIdentity } from '../core/agent-registry.js';
|
|
2
|
+
import { listCapabilities as listRegistryCapabilities, listTools as listRegistryTools } from '../core/registries.js';
|
|
2
3
|
import { buildReputationSummary } from '../core/reputation.js';
|
|
3
4
|
import { buildCircuitBreakerSnapshot } from '../core/circuit-breaker.js';
|
|
4
5
|
import { loadState } from '../core/state.js';
|
|
@@ -1195,28 +1196,26 @@ export function runDoctor(options = {}) {
|
|
|
1195
1196
|
console.log('✔ Cross-level duplicates: no duplicates across store levels');
|
|
1196
1197
|
}
|
|
1197
1198
|
}
|
|
1198
|
-
// Metadata consistency checks
|
|
1199
|
-
const capabilities =
|
|
1200
|
-
const tools =
|
|
1199
|
+
// Metadata consistency checks (capabilities/tools from dedicated registries)
|
|
1200
|
+
const capabilities = listRegistryCapabilities(options.cwd);
|
|
1201
|
+
const tools = listRegistryTools(options.cwd);
|
|
1201
1202
|
const metadataIssues = [];
|
|
1202
1203
|
// Check capabilities completeness
|
|
1203
1204
|
capabilities.forEach((cap) => {
|
|
1204
|
-
|
|
1205
|
-
if (!category) {
|
|
1205
|
+
if (!cap.category) {
|
|
1206
1206
|
metadataIssues.push(`Capability [${cap.id}] missing category`);
|
|
1207
1207
|
}
|
|
1208
|
-
if (!cap.
|
|
1209
|
-
metadataIssues.push(`Capability [${cap.id}] has empty
|
|
1208
|
+
if (!cap.name || cap.name.trim().length === 0) {
|
|
1209
|
+
metadataIssues.push(`Capability [${cap.id}] has empty name`);
|
|
1210
1210
|
}
|
|
1211
1211
|
});
|
|
1212
1212
|
// Check tools completeness
|
|
1213
1213
|
tools.forEach((tool) => {
|
|
1214
|
-
|
|
1215
|
-
if (!type) {
|
|
1214
|
+
if (!tool.type) {
|
|
1216
1215
|
metadataIssues.push(`Tool [${tool.id}] missing type`);
|
|
1217
1216
|
}
|
|
1218
|
-
if (!tool.
|
|
1219
|
-
metadataIssues.push(`Tool [${tool.id}] has empty
|
|
1217
|
+
if (!tool.name || tool.name.trim().length === 0) {
|
|
1218
|
+
metadataIssues.push(`Tool [${tool.id}] has empty name`);
|
|
1220
1219
|
}
|
|
1221
1220
|
});
|
|
1222
1221
|
if (metadataIssues.length > 0) {
|
|
@@ -1245,6 +1244,63 @@ export function runDoctor(options = {}) {
|
|
|
1245
1244
|
}
|
|
1246
1245
|
}
|
|
1247
1246
|
catch { /* non-fatal */ }
|
|
1247
|
+
// Check for machine-scoped items in project store (should be in user store)
|
|
1248
|
+
try {
|
|
1249
|
+
const machineInProject = [
|
|
1250
|
+
...state.active_constraints.filter((c) => c.scope === 'machine'),
|
|
1251
|
+
...state.recent_decisions.filter((d) => d.scope === 'machine'),
|
|
1252
|
+
...state.known_traps.filter((t) => t.scope === 'machine'),
|
|
1253
|
+
];
|
|
1254
|
+
if (machineInProject.length > 0) {
|
|
1255
|
+
const ids = machineInProject.map((i) => i.id).slice(0, 5);
|
|
1256
|
+
checks.push({
|
|
1257
|
+
name: 'machine_scope_placement',
|
|
1258
|
+
status: 'warn',
|
|
1259
|
+
message: `${machineInProject.length} machine-scoped item(s) in project store — consider promoting to user store with 'brainclaw migrate --promote-machine-items'`,
|
|
1260
|
+
details: ids,
|
|
1261
|
+
});
|
|
1262
|
+
if (!options.json) {
|
|
1263
|
+
console.warn(`⚠ ${machineInProject.length} machine-scoped item(s) in project store: ${ids.join(', ')}`);
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
else {
|
|
1267
|
+
checks.push({ name: 'machine_scope_placement', status: 'ok', message: 'No machine-scoped items misplaced in project store' });
|
|
1268
|
+
if (!options.json) {
|
|
1269
|
+
console.log('✔ Machine-scope placement: no misplaced items');
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
catch { /* non-fatal */ }
|
|
1274
|
+
// Workflow hygiene check (Phase 9)
|
|
1275
|
+
try {
|
|
1276
|
+
const activeClaims = listClaims(options.cwd).filter((c) => c.status === 'active');
|
|
1277
|
+
const inProgressPlans = state.plan_items.filter((p) => p.status === 'in_progress');
|
|
1278
|
+
const workflowIssues = [];
|
|
1279
|
+
if (activeClaims.length > 3) {
|
|
1280
|
+
workflowIssues.push(`${activeClaims.length} active claims — consider releasing finished ones`);
|
|
1281
|
+
}
|
|
1282
|
+
const unclaimedInProgress = inProgressPlans.filter((p) => !activeClaims.some((c) => c.plan_id === p.id));
|
|
1283
|
+
if (unclaimedInProgress.length > 0) {
|
|
1284
|
+
workflowIssues.push(`${unclaimedInProgress.length} in-progress plan(s) without a claim`);
|
|
1285
|
+
}
|
|
1286
|
+
if (workflowIssues.length > 0) {
|
|
1287
|
+
checks.push({
|
|
1288
|
+
name: 'workflow_hygiene',
|
|
1289
|
+
status: 'warn',
|
|
1290
|
+
message: `Workflow hygiene: ${workflowIssues.join('; ')}`,
|
|
1291
|
+
details: workflowIssues,
|
|
1292
|
+
});
|
|
1293
|
+
if (!options.json) {
|
|
1294
|
+
console.warn(`⚠ Workflow hygiene: ${workflowIssues.join('; ')}`);
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
else {
|
|
1298
|
+
checks.push({ name: 'workflow_hygiene', status: 'ok', message: 'Workflow hygiene OK' });
|
|
1299
|
+
if (!options.json)
|
|
1300
|
+
console.log('✔ Workflow hygiene: OK');
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
catch { /* non-fatal */ }
|
|
1248
1304
|
}
|
|
1249
1305
|
catch { /* non-fatal */ }
|
|
1250
1306
|
if (options.json) {
|
package/dist/commands/explore.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { loadState } from '../core/state.js';
|
|
2
1
|
import { memoryExists } from '../core/io.js';
|
|
2
|
+
import { listCapabilities, listTools } from '../core/registries.js';
|
|
3
3
|
export function runExplore(options = {}) {
|
|
4
4
|
const cwd = options.cwd ?? process.cwd();
|
|
5
5
|
if (!memoryExists(cwd)) {
|
|
6
6
|
console.error('Error: .brainclaw/ not found. Run `brainclaw init` first.');
|
|
7
7
|
process.exit(1);
|
|
8
8
|
}
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const tools = state.recent_decisions.filter((d) => d.tags.includes('tool'));
|
|
9
|
+
const capabilities = listCapabilities(cwd);
|
|
10
|
+
const tools = listTools(cwd);
|
|
12
11
|
console.log('\n╔════════════════════════════════════════════════════════╗');
|
|
13
12
|
console.log('║ Project Capabilities & Tools ║');
|
|
14
13
|
console.log('╚════════════════════════════════════════════════════════╝\n');
|
|
@@ -18,9 +17,8 @@ export function runExplore(options = {}) {
|
|
|
18
17
|
}
|
|
19
18
|
else {
|
|
20
19
|
capabilities.forEach((cap) => {
|
|
21
|
-
|
|
22
|
-
console.log(`
|
|
23
|
-
console.log(` Category: ${category}\n`);
|
|
20
|
+
console.log(` [${cap.id}] ${cap.name}`);
|
|
21
|
+
console.log(` Category: ${cap.category}\n`);
|
|
24
22
|
});
|
|
25
23
|
}
|
|
26
24
|
console.log(`🔧 Tools (${tools.length}):\n`);
|
|
@@ -29,9 +27,8 @@ export function runExplore(options = {}) {
|
|
|
29
27
|
}
|
|
30
28
|
else {
|
|
31
29
|
tools.forEach((tool) => {
|
|
32
|
-
|
|
33
|
-
console.log(`
|
|
34
|
-
console.log(` Type: ${type}\n`);
|
|
30
|
+
console.log(` [${tool.id}] ${tool.name}`);
|
|
31
|
+
console.log(` Type: ${tool.type}\n`);
|
|
35
32
|
});
|
|
36
33
|
}
|
|
37
34
|
if (capabilities.length === 0 && tools.length === 0) {
|
package/dist/commands/hooks.js
CHANGED
|
@@ -2,7 +2,7 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { memoryExists } from '../core/io.js';
|
|
4
4
|
import { loadConfig } from '../core/config.js';
|
|
5
|
-
import { BRAINCLAW_SECTION_START, BRAINCLAW_SECTION_END, upsertBrainclawSection } from '../core/agent-files.js';
|
|
5
|
+
import { BRAINCLAW_SECTION_START, BRAINCLAW_SECTION_END, upsertBrainclawSection, ensureClaudeCodeSettings } from '../core/agent-files.js';
|
|
6
6
|
/**
|
|
7
7
|
* Generate the Cursor MDC hook file content.
|
|
8
8
|
* Uses MDC frontmatter with `alwaysApply: true` so Cursor injects it
|
|
@@ -25,14 +25,14 @@ brainclaw context
|
|
|
25
25
|
This loads the shared project memory: active constraints, recent decisions, known traps,
|
|
26
26
|
open plan items, active claims, and the last handoff.
|
|
27
27
|
|
|
28
|
-
**Before finishing any session:**
|
|
29
|
-
|
|
30
|
-
\`\`\`bash
|
|
31
|
-
brainclaw claim release <id> # release claims you opened
|
|
32
|
-
brainclaw plan update <id> --status done # close plan items you completed
|
|
33
|
-
# or in one shot:
|
|
34
|
-
brainclaw session-end --auto-release
|
|
35
|
-
\`\`\`
|
|
28
|
+
**Before finishing any session:**
|
|
29
|
+
|
|
30
|
+
\`\`\`bash
|
|
31
|
+
brainclaw claim release <id> # release claims you opened
|
|
32
|
+
brainclaw plan update <id> --status done # close plan items you completed
|
|
33
|
+
# or in one shot:
|
|
34
|
+
brainclaw session-end --auto-release
|
|
35
|
+
\`\`\`
|
|
36
36
|
`;
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
@@ -55,14 +55,14 @@ brainclaw context
|
|
|
55
55
|
This gives you: active constraints, recent decisions, known traps, open plans, active claims,
|
|
56
56
|
and the last handoff note. Do not skip this step.
|
|
57
57
|
|
|
58
|
-
## SESSION END (before finishing)
|
|
59
|
-
|
|
60
|
-
\`\`\`bash
|
|
61
|
-
brainclaw claim release <id> # for each claim you hold
|
|
62
|
-
brainclaw plan update <id> --status done # for each plan item you completed
|
|
63
|
-
# or:
|
|
64
|
-
brainclaw session-end --auto-release
|
|
65
|
-
\`\`\`
|
|
58
|
+
## SESSION END (before finishing)
|
|
59
|
+
|
|
60
|
+
\`\`\`bash
|
|
61
|
+
brainclaw claim release <id> # for each claim you hold
|
|
62
|
+
brainclaw plan update <id> --status done # for each plan item you completed
|
|
63
|
+
# or:
|
|
64
|
+
brainclaw session-end --auto-release
|
|
65
|
+
\`\`\`
|
|
66
66
|
`;
|
|
67
67
|
}
|
|
68
68
|
export function writeHook(content, relativePath, cwd) {
|
|
@@ -100,6 +100,14 @@ export function runHooks(options = {}) {
|
|
|
100
100
|
const content = generateWindsurfHook(config.project_name);
|
|
101
101
|
results.push(writeHook(content, '.windsurfrules', cwd));
|
|
102
102
|
}
|
|
103
|
+
if (target === 'claude-code' || target === 'all') {
|
|
104
|
+
const autoResult = ensureClaudeCodeSettings(cwd);
|
|
105
|
+
results.push({
|
|
106
|
+
target: 'claude-code',
|
|
107
|
+
relativePath: autoResult.relativePath ?? '.claude/settings.local.json',
|
|
108
|
+
created: autoResult.created,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
103
111
|
for (const r of results) {
|
|
104
112
|
console.log(`✔ Hook written to ${r.relativePath} (${r.created ? 'created' : 'updated'})`);
|
|
105
113
|
}
|
|
@@ -118,6 +126,14 @@ export function writeDetectedAgentHooks(agentName, projectName, cwd) {
|
|
|
118
126
|
const content = generateWindsurfHook(projectName);
|
|
119
127
|
results.push(writeHook(content, '.windsurfrules', cwd));
|
|
120
128
|
}
|
|
129
|
+
if (agentName === 'claude-code') {
|
|
130
|
+
const autoResult = ensureClaudeCodeSettings(cwd);
|
|
131
|
+
results.push({
|
|
132
|
+
target: 'claude-code',
|
|
133
|
+
relativePath: autoResult.relativePath ?? '.claude/settings.local.json',
|
|
134
|
+
created: autoResult.created,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
121
137
|
return results;
|
|
122
138
|
}
|
|
123
139
|
//# sourceMappingURL=hooks.js.map
|