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.
- package/README.md +42 -11
- package/dist/cli.js +55 -1
- package/dist/commands/claude-desktop-extension.js +18 -0
- package/dist/commands/context.js +3 -1
- package/dist/commands/doctor.js +12 -5
- package/dist/commands/export.js +44 -0
- package/dist/commands/init.js +22 -6
- package/dist/commands/list-surface-tasks.js +39 -0
- package/dist/commands/mcp.js +86 -5
- package/dist/commands/reconcile.js +138 -0
- package/dist/commands/setup.js +19 -0
- package/dist/commands/status.js +17 -12
- package/dist/commands/surface-task-resource.js +35 -0
- package/dist/commands/surface-task.js +57 -0
- package/dist/commands/uninstall.js +145 -0
- package/dist/commands/update-surface-task.js +30 -0
- package/dist/core/agent-capability.js +184 -0
- package/dist/core/agent-context.js +24 -6
- package/dist/core/agent-files.js +18 -18
- package/dist/core/ai-surface-inventory.js +321 -0
- package/dist/core/ai-surface-tasks.js +40 -0
- package/dist/core/bootstrap.js +177 -0
- package/dist/core/claude-desktop-extension.js +224 -0
- package/dist/core/context.js +47 -24
- package/dist/core/ids.js +1 -0
- package/dist/core/instruction-templates.js +308 -0
- package/dist/core/io.js +1 -0
- package/dist/core/machine-profile.js +7 -1
- package/dist/core/migration.js +3 -1
- package/dist/core/schema.js +34 -0
- package/dist/core/setup-flow.js +191 -0
- package/dist/core/setup-state.js +30 -1
- package/dist/core/store-resolution.js +58 -0
- package/dist/core/workspace-projects.js +115 -0
- package/docs/architecture/project-refs.md +305 -0
- package/docs/cli.md +133 -1
- package/docs/integrations/agents.md +102 -150
- package/docs/integrations/overview.md +71 -45
- package/docs/quickstart.md +44 -111
- package/package.json +1 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import { loadConfig } from './config.js';
|
|
4
5
|
import { MEMORY_DIR } from './io.js';
|
|
6
|
+
import { summarizeWorkspaceProjects } from './workspace-projects.js';
|
|
5
7
|
/**
|
|
6
8
|
* Walk up the filesystem from `cwd`, collecting every `.brainclaw/` directory
|
|
7
9
|
* found along the way, up to (and including) `boundary`.
|
|
@@ -82,6 +84,49 @@ export function resolveTargetStore(cwd = process.cwd(), target = 'local', option
|
|
|
82
84
|
const match = chain.find((s) => s.role === 'user');
|
|
83
85
|
return match?.cwd ?? os.homedir();
|
|
84
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Resolve the most specific child store that should answer a context request.
|
|
89
|
+
*
|
|
90
|
+
* This keeps the current cwd by default, but when `target` clearly points inside
|
|
91
|
+
* a nested Brainclaw project (for example from a workspace root in folder mode),
|
|
92
|
+
* it returns that child store cwd instead.
|
|
93
|
+
*/
|
|
94
|
+
export function resolveContextStoreCwd(cwd = process.cwd(), target) {
|
|
95
|
+
const trimmedTarget = target?.trim();
|
|
96
|
+
if (!trimmedTarget) {
|
|
97
|
+
return cwd;
|
|
98
|
+
}
|
|
99
|
+
const primary = resolvePrimaryStore(cwd);
|
|
100
|
+
if (!primary) {
|
|
101
|
+
return cwd;
|
|
102
|
+
}
|
|
103
|
+
const absoluteTarget = resolveAbsoluteTargetPath(cwd, trimmedTarget);
|
|
104
|
+
if (!absoluteTarget) {
|
|
105
|
+
return cwd;
|
|
106
|
+
}
|
|
107
|
+
let config;
|
|
108
|
+
try {
|
|
109
|
+
config = loadConfig(primary.cwd);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return cwd;
|
|
113
|
+
}
|
|
114
|
+
const summary = summarizeWorkspaceProjects(primary.cwd, config);
|
|
115
|
+
if (summary.discovered_projects.length === 0) {
|
|
116
|
+
return cwd;
|
|
117
|
+
}
|
|
118
|
+
const candidates = summary.discovered_projects
|
|
119
|
+
.map((project) => path.resolve(primary.cwd, project.path))
|
|
120
|
+
.filter((candidatePath) => candidatePath !== primary.cwd)
|
|
121
|
+
.filter((candidatePath) => fs.existsSync(path.join(candidatePath, MEMORY_DIR)))
|
|
122
|
+
.sort((a, b) => b.length - a.length);
|
|
123
|
+
for (const candidate of candidates) {
|
|
124
|
+
if (isAtOrBelow(absoluteTarget, candidate)) {
|
|
125
|
+
return candidate;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return cwd;
|
|
129
|
+
}
|
|
85
130
|
/**
|
|
86
131
|
* Return true if `dir` is at or below `ancestor` in the filesystem hierarchy.
|
|
87
132
|
*/
|
|
@@ -90,6 +135,19 @@ function isAtOrBelow(dir, ancestor) {
|
|
|
90
135
|
// If relative path starts with '..', dir is above ancestor
|
|
91
136
|
return !rel.startsWith('..');
|
|
92
137
|
}
|
|
138
|
+
function resolveAbsoluteTargetPath(cwd, target) {
|
|
139
|
+
if (path.isAbsolute(target)) {
|
|
140
|
+
return path.resolve(target);
|
|
141
|
+
}
|
|
142
|
+
const joined = path.resolve(cwd, target);
|
|
143
|
+
if (fs.existsSync(joined)) {
|
|
144
|
+
return joined;
|
|
145
|
+
}
|
|
146
|
+
if (target.includes('/') || target.includes('\\') || target.startsWith('.')) {
|
|
147
|
+
return joined;
|
|
148
|
+
}
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
93
151
|
/**
|
|
94
152
|
* Infer the store role from config.yaml store_type field, or fall back to
|
|
95
153
|
* heuristics (presence of .git sibling = repo, no parent store = workspace).
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { loadGlobalRegistry, scanProject } from './global-registry.js';
|
|
4
|
+
const SKIP_DIRS = new Set([
|
|
5
|
+
'.brainclaw',
|
|
6
|
+
'.git',
|
|
7
|
+
'node_modules',
|
|
8
|
+
'dist',
|
|
9
|
+
'dist-test',
|
|
10
|
+
'build',
|
|
11
|
+
'coverage',
|
|
12
|
+
'.venv',
|
|
13
|
+
'venv',
|
|
14
|
+
'__pycache__',
|
|
15
|
+
'target',
|
|
16
|
+
'vendor',
|
|
17
|
+
'.next',
|
|
18
|
+
'.nuxt',
|
|
19
|
+
]);
|
|
20
|
+
export function summarizeWorkspaceProjects(cwd, config) {
|
|
21
|
+
const configuredProjects = config.projects?.known ?? [];
|
|
22
|
+
const usesFolderResolution = config.project_mode === 'multi-project' && (config.projects?.strategy ?? 'manual') === 'folder';
|
|
23
|
+
const discovered = new Map();
|
|
24
|
+
for (const name of configuredProjects) {
|
|
25
|
+
const key = `config:${name}`;
|
|
26
|
+
discovered.set(key, {
|
|
27
|
+
path: name,
|
|
28
|
+
relative_path: name,
|
|
29
|
+
project_name: name,
|
|
30
|
+
source: 'config',
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (usesFolderResolution) {
|
|
34
|
+
for (const project of collectRegistryProjectsUnder(cwd)) {
|
|
35
|
+
const normalized = path.resolve(project.path);
|
|
36
|
+
if (normalized === path.resolve(cwd)) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
discovered.set(`path:${normalized}`, {
|
|
40
|
+
path: normalized,
|
|
41
|
+
relative_path: path.relative(cwd, normalized) || '.',
|
|
42
|
+
project_id: project.project_id,
|
|
43
|
+
project_name: project.project_name,
|
|
44
|
+
source: 'registry',
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
for (const project of scanNestedBrainclawProjects(cwd)) {
|
|
48
|
+
const normalized = path.resolve(project.path);
|
|
49
|
+
if (normalized === path.resolve(cwd)) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (!discovered.has(`path:${normalized}`)) {
|
|
53
|
+
discovered.set(`path:${normalized}`, {
|
|
54
|
+
path: normalized,
|
|
55
|
+
relative_path: path.relative(cwd, normalized) || '.',
|
|
56
|
+
project_id: project.project_id,
|
|
57
|
+
project_name: project.project_name,
|
|
58
|
+
source: 'filesystem',
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
strategy: config.projects?.strategy ?? 'manual',
|
|
65
|
+
configured_projects: configuredProjects,
|
|
66
|
+
discovered_projects: [...discovered.values()].sort((a, b) => a.relative_path.localeCompare(b.relative_path)),
|
|
67
|
+
effective_project_count: discovered.size,
|
|
68
|
+
uses_folder_resolution: usesFolderResolution,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export function scanNestedBrainclawProjects(rootDir, maxDepth = 6) {
|
|
72
|
+
const resolvedRoot = path.resolve(rootDir);
|
|
73
|
+
const results = new Map();
|
|
74
|
+
function walk(dir, depth) {
|
|
75
|
+
if (depth > maxDepth) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
let entries;
|
|
79
|
+
try {
|
|
80
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
for (const entry of entries) {
|
|
86
|
+
if (!entry.isDirectory())
|
|
87
|
+
continue;
|
|
88
|
+
if (SKIP_DIRS.has(entry.name))
|
|
89
|
+
continue;
|
|
90
|
+
if (entry.name.startsWith('.') && entry.name !== '.brainclaw')
|
|
91
|
+
continue;
|
|
92
|
+
const childDir = path.join(dir, entry.name);
|
|
93
|
+
const maybeProject = scanProject(childDir);
|
|
94
|
+
if (maybeProject) {
|
|
95
|
+
results.set(path.resolve(maybeProject.path), maybeProject);
|
|
96
|
+
}
|
|
97
|
+
walk(childDir, depth + 1);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
walk(resolvedRoot, 1);
|
|
101
|
+
return [...results.values()].sort((a, b) => a.path.localeCompare(b.path));
|
|
102
|
+
}
|
|
103
|
+
function collectRegistryProjectsUnder(rootDir) {
|
|
104
|
+
const registry = loadGlobalRegistry();
|
|
105
|
+
if (!registry) {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
const resolvedRoot = path.resolve(rootDir);
|
|
109
|
+
return registry.projects.filter((project) => isWithinRoot(project.path, resolvedRoot));
|
|
110
|
+
}
|
|
111
|
+
function isWithinRoot(candidatePath, rootDir) {
|
|
112
|
+
const relative = path.relative(rootDir, path.resolve(candidatePath));
|
|
113
|
+
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=workspace-projects.js.map
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
# Project Refs for Multi-Project Navigation
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
In a multi-project workspace, agents should be able to address any known project from anywhere in the workspace without depending on the current working directory.
|
|
6
|
+
|
|
7
|
+
The core primitive for this is a stable `project_ref`.
|
|
8
|
+
|
|
9
|
+
Examples:
|
|
10
|
+
|
|
11
|
+
- `dev/repos/global`
|
|
12
|
+
- `applications/lodestar`
|
|
13
|
+
- `core_services/postgres`
|
|
14
|
+
|
|
15
|
+
This lets Brainclaw support direct project navigation commands such as:
|
|
16
|
+
|
|
17
|
+
- `brainclaw projects`
|
|
18
|
+
- `brainclaw project applications/lodestar`
|
|
19
|
+
- `brainclaw context --project applications/lodestar`
|
|
20
|
+
- `brainclaw children dev/repos/global`
|
|
21
|
+
- `brainclaw ancestors applications/lodestar`
|
|
22
|
+
- `brainclaw dependencies applications/lodestar`
|
|
23
|
+
- `brainclaw locate dev/repos/global/applications/lodestar/src/app.ts`
|
|
24
|
+
|
|
25
|
+
The same addressing model must exist over MCP.
|
|
26
|
+
|
|
27
|
+
## Why
|
|
28
|
+
|
|
29
|
+
Current workspace-centric behavior is still too dependent on `cwd` and path heuristics:
|
|
30
|
+
|
|
31
|
+
- `brainclaw context --for <path>` can help rerank context
|
|
32
|
+
- in folder-mode workspaces it can now resolve a child store for some path-shaped targets
|
|
33
|
+
- but the mental model is still "where am I on disk?"
|
|
34
|
+
|
|
35
|
+
For agents, this is weaker than "which project am I addressing?"
|
|
36
|
+
|
|
37
|
+
`project_ref` should become the natural addressing unit for:
|
|
38
|
+
|
|
39
|
+
- context lookup
|
|
40
|
+
- workspace navigation
|
|
41
|
+
- parent/child traversal
|
|
42
|
+
- dependency traversal
|
|
43
|
+
- future project-scoped MCP tools
|
|
44
|
+
|
|
45
|
+
## Core Model
|
|
46
|
+
|
|
47
|
+
Each known project keeps its internal `project_id`.
|
|
48
|
+
|
|
49
|
+
Each project also gets a stable human-readable `project_ref`:
|
|
50
|
+
|
|
51
|
+
- derived from the workspace-relative path
|
|
52
|
+
- normalized with forward slashes
|
|
53
|
+
- unique within the workspace
|
|
54
|
+
|
|
55
|
+
Examples:
|
|
56
|
+
|
|
57
|
+
- workspace root: `.`
|
|
58
|
+
- child repo: `dev/repos/global`
|
|
59
|
+
- nested project: `dev/repos/global/applications/lodestar`
|
|
60
|
+
|
|
61
|
+
The registry for a workspace project should expose at least:
|
|
62
|
+
|
|
63
|
+
- `project_id`
|
|
64
|
+
- `project_ref`
|
|
65
|
+
- `project_name`
|
|
66
|
+
- `relative_path`
|
|
67
|
+
- `absolute_path`
|
|
68
|
+
- `workspace_root`
|
|
69
|
+
- `parent_ref`
|
|
70
|
+
- `aliases`
|
|
71
|
+
- `store_present`
|
|
72
|
+
- `source`
|
|
73
|
+
- `dependencies`
|
|
74
|
+
|
|
75
|
+
## Naming Rules
|
|
76
|
+
|
|
77
|
+
Canonical rule:
|
|
78
|
+
|
|
79
|
+
- `project_ref` is the workspace-relative path to the project root
|
|
80
|
+
|
|
81
|
+
Short aliases:
|
|
82
|
+
|
|
83
|
+
- the final path segment may be used as an alias
|
|
84
|
+
- only when unique within the workspace
|
|
85
|
+
- ambiguous aliases must fail with a disambiguation error
|
|
86
|
+
|
|
87
|
+
Examples:
|
|
88
|
+
|
|
89
|
+
- `applications/lodestar` may have alias `lodestar`
|
|
90
|
+
- if two projects end with `api`, `brainclaw project api` must fail and suggest full refs
|
|
91
|
+
|
|
92
|
+
This keeps the model simple:
|
|
93
|
+
|
|
94
|
+
- canonical ref is always deterministic
|
|
95
|
+
- short names are optional ergonomics, not identity
|
|
96
|
+
|
|
97
|
+
## Project Resolution
|
|
98
|
+
|
|
99
|
+
Resolution should work from anywhere in the workspace.
|
|
100
|
+
|
|
101
|
+
The resolver accepts:
|
|
102
|
+
|
|
103
|
+
- exact `project_ref`
|
|
104
|
+
- exact `project_id`
|
|
105
|
+
- unique short alias
|
|
106
|
+
- absolute path to a project root
|
|
107
|
+
- absolute or relative path inside a project
|
|
108
|
+
|
|
109
|
+
The resolver returns:
|
|
110
|
+
|
|
111
|
+
- the matched project record
|
|
112
|
+
- the resolved project root
|
|
113
|
+
- the matched method: `ref`, `id`, `alias`, or `path`
|
|
114
|
+
|
|
115
|
+
Resolution priority:
|
|
116
|
+
|
|
117
|
+
1. exact `project_ref`
|
|
118
|
+
2. exact `project_id`
|
|
119
|
+
3. unique alias
|
|
120
|
+
4. path-to-project containment
|
|
121
|
+
|
|
122
|
+
If multiple matches remain, Brainclaw must stop and return a clear ambiguity error.
|
|
123
|
+
|
|
124
|
+
## CLI Surface
|
|
125
|
+
|
|
126
|
+
The minimal agent-first CLI surface should be:
|
|
127
|
+
|
|
128
|
+
### `brainclaw projects`
|
|
129
|
+
|
|
130
|
+
List known projects in the current workspace.
|
|
131
|
+
|
|
132
|
+
Fields:
|
|
133
|
+
|
|
134
|
+
- `project_ref`
|
|
135
|
+
- `project_name`
|
|
136
|
+
- `relative_path`
|
|
137
|
+
- `parent_ref`
|
|
138
|
+
- `store_present`
|
|
139
|
+
|
|
140
|
+
### `brainclaw project <ref>`
|
|
141
|
+
|
|
142
|
+
Show a compact project card.
|
|
143
|
+
|
|
144
|
+
Fields:
|
|
145
|
+
|
|
146
|
+
- `project_id`
|
|
147
|
+
- `project_ref`
|
|
148
|
+
- `aliases`
|
|
149
|
+
- `absolute_path`
|
|
150
|
+
- `parent_ref`
|
|
151
|
+
- `children`
|
|
152
|
+
- `dependencies`
|
|
153
|
+
- store health summary
|
|
154
|
+
|
|
155
|
+
### `brainclaw context --project <ref>`
|
|
156
|
+
|
|
157
|
+
Resolve the target project first, then build context from that store.
|
|
158
|
+
|
|
159
|
+
Notes:
|
|
160
|
+
|
|
161
|
+
- this is stronger than `context --for`
|
|
162
|
+
- `--for` still helps ranking within the resolved project
|
|
163
|
+
|
|
164
|
+
Example:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
brainclaw context --project applications/lodestar --for src/app.ts
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### `brainclaw children <ref>`
|
|
171
|
+
|
|
172
|
+
Return direct child projects.
|
|
173
|
+
|
|
174
|
+
### `brainclaw ancestors <ref>`
|
|
175
|
+
|
|
176
|
+
Return the project chain from parent to workspace root.
|
|
177
|
+
|
|
178
|
+
### `brainclaw dependencies <ref>`
|
|
179
|
+
|
|
180
|
+
Return declared or detected project dependencies.
|
|
181
|
+
|
|
182
|
+
### `brainclaw locate <path>`
|
|
183
|
+
|
|
184
|
+
Resolve any path to the owning project.
|
|
185
|
+
|
|
186
|
+
This is especially useful for agents:
|
|
187
|
+
|
|
188
|
+
- start from a changed file
|
|
189
|
+
- ask Brainclaw which project owns it
|
|
190
|
+
- then request context for that project
|
|
191
|
+
|
|
192
|
+
## MCP Surface
|
|
193
|
+
|
|
194
|
+
The MCP equivalents should mirror the CLI rather than invent a second addressing model.
|
|
195
|
+
|
|
196
|
+
Suggested tools:
|
|
197
|
+
|
|
198
|
+
- `bclaw_list_projects`
|
|
199
|
+
- `bclaw_get_project`
|
|
200
|
+
- `bclaw_get_project_context`
|
|
201
|
+
- `bclaw_list_project_children`
|
|
202
|
+
- `bclaw_list_project_ancestors`
|
|
203
|
+
- `bclaw_list_project_dependencies`
|
|
204
|
+
- `bclaw_locate_project`
|
|
205
|
+
|
|
206
|
+
All of them should accept `project_ref` as the primary selector.
|
|
207
|
+
|
|
208
|
+
`bclaw_get_context` may continue to exist, but multi-project agents should prefer `bclaw_get_project_context`.
|
|
209
|
+
|
|
210
|
+
## Hierarchy Semantics
|
|
211
|
+
|
|
212
|
+
Hierarchy comes from project roots on disk.
|
|
213
|
+
|
|
214
|
+
Definitions:
|
|
215
|
+
|
|
216
|
+
- parent: nearest known project root above the current project
|
|
217
|
+
- child: known project whose nearest known parent is the current project
|
|
218
|
+
- ancestor: repeated parent chain
|
|
219
|
+
|
|
220
|
+
This is path-derived and deterministic.
|
|
221
|
+
|
|
222
|
+
## Dependency Semantics
|
|
223
|
+
|
|
224
|
+
Dependencies are different from hierarchy.
|
|
225
|
+
|
|
226
|
+
Dependencies should support two sources:
|
|
227
|
+
|
|
228
|
+
- declared links in Brainclaw metadata
|
|
229
|
+
- detected links from repo/workspace tooling when reliable
|
|
230
|
+
|
|
231
|
+
Examples:
|
|
232
|
+
|
|
233
|
+
- monorepo package dependencies
|
|
234
|
+
- service depends on shared database project
|
|
235
|
+
- app depends on auth service
|
|
236
|
+
|
|
237
|
+
The first iteration should allow declared dependencies first.
|
|
238
|
+
|
|
239
|
+
Auto-detection can remain additive.
|
|
240
|
+
|
|
241
|
+
## Storage Direction
|
|
242
|
+
|
|
243
|
+
This does not require replacing current project ids or store layout.
|
|
244
|
+
|
|
245
|
+
It requires a workspace project registry that can be rebuilt or refreshed non-destructively.
|
|
246
|
+
|
|
247
|
+
Likely location:
|
|
248
|
+
|
|
249
|
+
- workspace-level discovery inventory
|
|
250
|
+
|
|
251
|
+
Likely persisted fields:
|
|
252
|
+
|
|
253
|
+
- stable `project_ref`
|
|
254
|
+
- alias set
|
|
255
|
+
- hierarchy links
|
|
256
|
+
- declared dependency links
|
|
257
|
+
|
|
258
|
+
This should stay clearly separate from canonical memory items such as decisions and constraints.
|
|
259
|
+
|
|
260
|
+
## Migration Strategy
|
|
261
|
+
|
|
262
|
+
The migration should be low-risk and incremental.
|
|
263
|
+
|
|
264
|
+
Phase 1:
|
|
265
|
+
|
|
266
|
+
- introduce `project_ref` in workspace discovery/registry
|
|
267
|
+
- expose `brainclaw projects`
|
|
268
|
+
- expose `brainclaw locate`
|
|
269
|
+
|
|
270
|
+
Phase 2:
|
|
271
|
+
|
|
272
|
+
- add `context --project <ref>`
|
|
273
|
+
- keep current `context --for <path>` behavior
|
|
274
|
+
- when `--project` is present, it wins over cwd heuristics
|
|
275
|
+
|
|
276
|
+
Phase 3:
|
|
277
|
+
|
|
278
|
+
- add `children` and `ancestors`
|
|
279
|
+
- add MCP equivalents
|
|
280
|
+
|
|
281
|
+
Phase 4:
|
|
282
|
+
|
|
283
|
+
- add declared dependencies
|
|
284
|
+
- optionally add auto-detection
|
|
285
|
+
|
|
286
|
+
## Non-Goals
|
|
287
|
+
|
|
288
|
+
This design does not require:
|
|
289
|
+
|
|
290
|
+
- replacing `project_id`
|
|
291
|
+
- removing cwd-based commands
|
|
292
|
+
- making aliases mandatory
|
|
293
|
+
- making dependency inference perfect in the first release
|
|
294
|
+
|
|
295
|
+
## Recommendation
|
|
296
|
+
|
|
297
|
+
The first implementation slice should be:
|
|
298
|
+
|
|
299
|
+
1. add `project_ref` to workspace project discovery
|
|
300
|
+
2. add a project resolver shared by CLI and MCP
|
|
301
|
+
3. add `brainclaw projects`
|
|
302
|
+
4. add `brainclaw context --project <ref>`
|
|
303
|
+
5. add `brainclaw locate <path>`
|
|
304
|
+
|
|
305
|
+
That is enough to give agents a stable and simple project-addressing model without a risky refactor.
|
package/docs/cli.md
CHANGED
|
@@ -60,6 +60,85 @@ brainclaw init --topology sidecar
|
|
|
60
60
|
brainclaw init --project-mode multi-project --project-strategy folder
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
+
### `brainclaw machine-profile`
|
|
64
|
+
|
|
65
|
+
Detect and persist machine-level capabilities, including other local AI work surfaces on the same machine.
|
|
66
|
+
|
|
67
|
+
This is the inventory Brainclaw uses to distinguish coding agents from desktop AI apps or adjacent surfaces such as:
|
|
68
|
+
|
|
69
|
+
- `ChatGPT Desktop`
|
|
70
|
+
- `Claude Desktop`
|
|
71
|
+
- `Claude Cowork`
|
|
72
|
+
- `Gemini Web`
|
|
73
|
+
- `Gemini CLI / Antigravity`
|
|
74
|
+
|
|
75
|
+
| Option | Description |
|
|
76
|
+
|---|---|
|
|
77
|
+
| `--refresh` | Force regeneration even if a cached profile already exists |
|
|
78
|
+
| `--json` | Output as JSON |
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
brainclaw machine-profile
|
|
82
|
+
brainclaw machine-profile --refresh
|
|
83
|
+
brainclaw machine-profile --refresh --json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Use this when you want Brainclaw to detect what AI work surfaces are actually available on the current machine before choosing an onboarding path or queueing work for another surface.
|
|
87
|
+
|
|
88
|
+
### `brainclaw upgrade`
|
|
89
|
+
|
|
90
|
+
Upgrade the local Brainclaw store layout and refresh managed agent files when a release changes persisted schema or generated workspace integrations.
|
|
91
|
+
|
|
92
|
+
| Option | Description |
|
|
93
|
+
|---|---|
|
|
94
|
+
| `--json` | Output as JSON |
|
|
95
|
+
| `--dry-run` | Preview what would be upgraded without writing |
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
brainclaw upgrade
|
|
99
|
+
brainclaw upgrade --dry-run
|
|
100
|
+
brainclaw upgrade --dry-run --json
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`upgrade` only covers store and generated-file migrations. On complex workspaces, it does not refresh machine detection, agent inventory, or brownfield bootstrap state by itself.
|
|
104
|
+
|
|
105
|
+
### `brainclaw reconcile`
|
|
106
|
+
|
|
107
|
+
Refresh machine, agent, and bootstrap state after a package update or when onboarding an already-initialized multi-store workspace.
|
|
108
|
+
|
|
109
|
+
This is the command to use when `brainclaw upgrade` reports no schema migration, but the installed release still introduces new workspace-centric behavior that depends on:
|
|
110
|
+
|
|
111
|
+
- a refreshed `machine-profile`
|
|
112
|
+
- a refreshed `agent-inventory`
|
|
113
|
+
- refreshed bootstrap state for the current store and any nested Brainclaw stores discovered under a `multi-project` + `folder` workspace
|
|
114
|
+
|
|
115
|
+
| Option | Description |
|
|
116
|
+
|---|---|
|
|
117
|
+
| `--json` | Output as JSON |
|
|
118
|
+
| `--dry-run` | Preview the reconciliation plan without writing |
|
|
119
|
+
| `--apply-bootstrap` | Apply bootstrap suggestions across all selected stores after refresh |
|
|
120
|
+
| `-y, --yes` | Skip confirmation prompts for multi-store bootstrap apply |
|
|
121
|
+
| `--skip-machine-profile` | Skip machine profile refresh |
|
|
122
|
+
| `--skip-agent-inventory` | Skip agent inventory refresh |
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
brainclaw reconcile --dry-run --json
|
|
126
|
+
brainclaw reconcile
|
|
127
|
+
brainclaw reconcile --apply-bootstrap -y
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Recommended post-update flow for an existing complex workspace:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
brainclaw upgrade --dry-run --json
|
|
134
|
+
brainclaw reconcile --dry-run --json
|
|
135
|
+
brainclaw reconcile --apply-bootstrap -y
|
|
136
|
+
brainclaw context --json
|
|
137
|
+
brainclaw doctor --json
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
For a `multi-project` workspace using `projects.strategy: folder`, `reconcile` treats the current store as the workspace root and plans refreshes for nested child stores that already contain their own `.brainclaw/` directories.
|
|
141
|
+
|
|
63
142
|
### `brainclaw status`
|
|
64
143
|
|
|
65
144
|
Show the current state of project memory.
|
|
@@ -75,6 +154,8 @@ brainclaw status --json
|
|
|
75
154
|
brainclaw status --markdown
|
|
76
155
|
```
|
|
77
156
|
|
|
157
|
+
In `multi-project` mode, status now reports the effective project count resolved for the workspace. With `projects.strategy: folder`, that includes child stores discovered from nested `.brainclaw/` directories even when `config.projects.known` is still empty.
|
|
158
|
+
|
|
78
159
|
### `brainclaw doctor`
|
|
79
160
|
|
|
80
161
|
Run health checks on config, state, and generated views.
|
|
@@ -94,6 +175,8 @@ brainclaw doctor --fix-agent-ignore
|
|
|
94
175
|
|
|
95
176
|
When Brainclaw detects generated local agent files such as `.mcp.json` or `.claude/settings.local.json` inside a Git repo, `doctor` warns if they are not ignored or are still tracked. `--fix-agent-ignore` only updates `.gitignore`; if a file is already tracked you still need to untrack it with `git rm --cached <path>`.
|
|
96
177
|
|
|
178
|
+
In `multi-project` mode with `projects.strategy: folder`, `doctor` now checks the effective workspace project set, not just `config.projects.known`. That avoids false positives on workspaces that resolve child stores from the filesystem or global project registry.
|
|
179
|
+
|
|
97
180
|
### `brainclaw rebuild`
|
|
98
181
|
|
|
99
182
|
Regenerate `project.md` from canonical state. No options.
|
|
@@ -148,6 +231,54 @@ brainclaw env --agent-tooling
|
|
|
148
231
|
|
|
149
232
|
When the project does not pin a local release channel, `brainclaw env` checks the public npm `latest` channel for installable updates. Projects can override that with `brainclaw_update_source`, for example to use `prelaunch` or a local-pack manifest.
|
|
150
233
|
|
|
234
|
+
### `brainclaw surface-task <subcommand>`
|
|
235
|
+
|
|
236
|
+
Manage queued tasks for non-editing AI work surfaces such as `ChatGPT Desktop`, `Claude Desktop`, or `Gemini Web`.
|
|
237
|
+
|
|
238
|
+
This command is useful when the active coding agent should keep building in the repo, but another local AI surface would be a better fit for a related task such as:
|
|
239
|
+
|
|
240
|
+
- generating a visual asset
|
|
241
|
+
- drafting polished copy
|
|
242
|
+
- writing a release summary
|
|
243
|
+
- doing side research or structured analysis
|
|
244
|
+
|
|
245
|
+
Supported subcommands:
|
|
246
|
+
|
|
247
|
+
- `create`
|
|
248
|
+
- `list`
|
|
249
|
+
- `update`
|
|
250
|
+
|
|
251
|
+
| Option | Description |
|
|
252
|
+
|---|---|
|
|
253
|
+
| `--target <surface>` | Target surface such as `chatgpt`, `claude`, or `gemini` |
|
|
254
|
+
| `--kind <kind>` | `visual_asset`, `draft`, `summary`, `analysis`, `research`, or `custom` |
|
|
255
|
+
| `--instructions <text>` | Detailed task instructions |
|
|
256
|
+
| `--output <paths...>` | Expected output files or deliverables |
|
|
257
|
+
| `--tag <tags...>` | Optional tags |
|
|
258
|
+
| `--path <paths...>` | Related repo paths |
|
|
259
|
+
| `--status <status>` | For `list` filtering or `update`: `queued`, `in_progress`, `completed`, `cancelled`, `failed` |
|
|
260
|
+
| `--result <text>` | Result note when updating a task |
|
|
261
|
+
| `--all` | Include completed, cancelled, and failed tasks in `list` |
|
|
262
|
+
| `--json` | Output as JSON for `list` |
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
brainclaw surface-task create "Generate homepage hero visual" \
|
|
266
|
+
--target chatgpt \
|
|
267
|
+
--kind visual_asset \
|
|
268
|
+
--instructions "Create a lightweight SaaS hero visual in PNG format." \
|
|
269
|
+
--output assets/hero-home.png \
|
|
270
|
+
--path src/pages/Home.tsx
|
|
271
|
+
|
|
272
|
+
brainclaw surface-task list
|
|
273
|
+
|
|
274
|
+
brainclaw surface-task update ast_12345678 \
|
|
275
|
+
--status completed \
|
|
276
|
+
--result "Saved the visual to assets/hero-home.png" \
|
|
277
|
+
--output assets/hero-home.png
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
These tasks are local project coordination state. They do not execute automatically yet. The intended model is that Brainclaw can queue work for another local AI surface so that the next session on that surface can pick it up cleanly.
|
|
281
|
+
|
|
151
282
|
---
|
|
152
283
|
|
|
153
284
|
## Memory Management
|
|
@@ -787,7 +918,7 @@ Generate compact, prompt-ready context for agents.
|
|
|
787
918
|
|
|
788
919
|
| Option | Description |
|
|
789
920
|
|---|---|
|
|
790
|
-
| `--for <path>` | Scope context to a file or path |
|
|
921
|
+
| `--for <path>` | Scope context to a file or path; in folder-mode workspaces, child project paths resolve the matching nested store automatically |
|
|
791
922
|
| `--project <name>` | Filter by project |
|
|
792
923
|
| `--agent <name>` | Filter by agent |
|
|
793
924
|
| `--host <name>` | Filter by host |
|
|
@@ -807,6 +938,7 @@ Generate compact, prompt-ready context for agents.
|
|
|
807
938
|
|
|
808
939
|
```bash
|
|
809
940
|
brainclaw context --for src/auth/routes.ts --digest
|
|
941
|
+
brainclaw context --for applications/lodestar/src/app.ts --json
|
|
810
942
|
brainclaw context --json --max-chars 1200
|
|
811
943
|
brainclaw context --explain
|
|
812
944
|
brainclaw context --since-session --max-items 20
|