@monoes/monomindcli 1.10.23 → 1.10.24
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.
|
@@ -1,197 +1,139 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: monomind:understand
|
|
3
|
-
description: "Monomind — Run semantic enrichment on the current project's monograph knowledge graph.
|
|
3
|
+
description: "Monomind — Run semantic enrichment on the current project's monograph knowledge graph. Uses the active Claude Code session for LLM work — no API key needed."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /monomind:understand — Semantic Enrichment
|
|
7
7
|
|
|
8
|
-
Enriches the current project's monograph knowledge graph with
|
|
9
|
-
|
|
8
|
+
Enriches the current project's monograph knowledge graph with summaries, architectural
|
|
9
|
+
layers, and semantic relationships.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
**Designed to run inside Claude Code** — uses YOUR current session for LLM work via
|
|
12
|
+
the Task tool. No `ANTHROPIC_API_KEY` required. The script handles layer detection
|
|
13
|
+
and DB writes; you (Claude) handle per-file summarization.
|
|
12
14
|
|
|
13
15
|
## Parse Arguments
|
|
14
16
|
|
|
15
|
-
Parse `$ARGUMENTS` for these
|
|
16
|
-
|
|
17
|
-
- `--dir <path>` — project directory
|
|
18
|
-
- `--db <path>` —
|
|
19
|
-
- `--
|
|
20
|
-
- `--
|
|
21
|
-
- `--
|
|
22
|
-
- `--no-llm` — heuristic-only mode: detect layers from file paths, no API calls
|
|
23
|
-
- `--layers-only` — skip per-file analysis, only (re-)detect architectural layers
|
|
24
|
-
- `--incremental` — re-analyze only files changed since the last run (uses git diff)
|
|
25
|
-
- `--onboard` — generate an ONBOARDING.md guide from the enriched graph
|
|
26
|
-
- `--onboard-out <path>` — where to write the onboarding guide (default: `<dir>/ONBOARDING.md`)
|
|
27
|
-
- `--batch-size <N>` — files per LLM batch (default: 5, increase for faster analysis)
|
|
17
|
+
Parse `$ARGUMENTS` for these flags:
|
|
18
|
+
|
|
19
|
+
- `--dir <path>` — project directory (default: cwd)
|
|
20
|
+
- `--db <path>` — monograph.db path (default: `<dir>/.monomind/monograph.db`)
|
|
21
|
+
- `--full` — force full re-analysis
|
|
22
|
+
- `--no-llm` — heuristic-only mode (no per-file summaries)
|
|
23
|
+
- `--layers-only` — skip per-file analysis, only re-detect layers
|
|
28
24
|
- `--max-files <N>` — stop after N files (0 = all)
|
|
29
|
-
- `--dry-run` — show what would happen
|
|
25
|
+
- `--dry-run` — show what would happen, don't write
|
|
30
26
|
|
|
31
|
-
|
|
27
|
+
Bare path argument → `--dir`.
|
|
32
28
|
|
|
33
29
|
---
|
|
34
30
|
|
|
35
|
-
## Step 1: Locate project and
|
|
31
|
+
## Step 1: Locate project, DB, and script
|
|
36
32
|
|
|
37
33
|
```bash
|
|
38
34
|
DIR="${ARGUMENTS_dir:-$(pwd)}"
|
|
39
35
|
DB="${ARGUMENTS_db:-$DIR/.monomind/monograph.db}"
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
1. Resolve `DIR` to an absolute path.
|
|
43
|
-
2. Check that `$DB` exists. If not, tell the user:
|
|
44
|
-
> monograph.db not found at `$DB`. Build the graph first:
|
|
45
|
-
> ```bash
|
|
46
|
-
> npx monomind monograph build
|
|
47
|
-
> ```
|
|
48
|
-
> Then re-run `/monomind:understand`.
|
|
49
|
-
And STOP.
|
|
50
|
-
|
|
51
|
-
---
|
|
52
36
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
The `understand-analyze.mjs` script ships with `@monomind/cli`. Find it:
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
# Try npm root (global install / homebrew)
|
|
37
|
+
# Find understand-analyze.mjs (ships with monomind globally)
|
|
59
38
|
GLOBAL_ROOT=$(npm root -g 2>/dev/null)
|
|
60
|
-
SCRIPT="$GLOBAL_ROOT/@monomind/cli/scripts/understand-analyze.mjs"
|
|
61
|
-
|
|
62
|
-
# If not found globally, try npx resolve
|
|
63
|
-
if [ ! -f "$SCRIPT" ]; then
|
|
64
|
-
SCRIPT=$(node -e "try{console.log(require.resolve('@monomind/cli/scripts/understand-analyze.mjs'))}catch{}" 2>/dev/null)
|
|
65
|
-
fi
|
|
66
|
-
|
|
67
|
-
# Fallback: walk up from the running CLI's __dirname
|
|
68
|
-
if [ ! -f "$SCRIPT" ]; then
|
|
69
|
-
SCRIPT=$(node -e "
|
|
70
|
-
const {createRequire} = require('module');
|
|
71
|
-
const r = createRequire(require.resolve('monomind'));
|
|
72
|
-
try { console.log(r.resolve('@monomind/cli/scripts/understand-analyze.mjs')); } catch {}
|
|
73
|
-
" 2>/dev/null)
|
|
74
|
-
fi
|
|
39
|
+
SCRIPT="$GLOBAL_ROOT/monomind/packages/@monomind/cli/scripts/understand-analyze.mjs"
|
|
40
|
+
[ ! -f "$SCRIPT" ] && SCRIPT="$GLOBAL_ROOT/@monoes/monomindcli/scripts/understand-analyze.mjs"
|
|
75
41
|
```
|
|
76
42
|
|
|
77
|
-
If
|
|
78
|
-
>
|
|
79
|
-
> Update monomind: `npm install -g monomind@latest`
|
|
80
|
-
|
|
81
|
-
And STOP.
|
|
43
|
+
If `$DB` does not exist:
|
|
44
|
+
> monograph.db not found at `$DB`. Build it first: `npx monomind monograph build`
|
|
82
45
|
|
|
83
|
-
|
|
46
|
+
If `$SCRIPT` does not exist:
|
|
47
|
+
> understand engine missing. Update: `npm install -g monomind@latest`
|
|
84
48
|
|
|
85
|
-
|
|
49
|
+
In either case, STOP.
|
|
86
50
|
|
|
87
|
-
|
|
88
|
-
- `$DIR/.understand/knowledge-graph.json`
|
|
89
|
-
- `$DIR/.understand/graph.json`
|
|
90
|
-
- `$DIR/.ua/graph.json`
|
|
51
|
+
---
|
|
91
52
|
|
|
92
|
-
|
|
53
|
+
## Step 2: Run the script in heuristic mode (always — fast and deterministic)
|
|
93
54
|
|
|
94
|
-
|
|
55
|
+
This step is non-negotiable. The script handles:
|
|
56
|
+
- File node discovery from monograph.db
|
|
57
|
+
- Heuristic layer detection from file paths
|
|
58
|
+
- DB writes (community_id + properties)
|
|
59
|
+
- graph.json emission to `.understand/knowledge-graph.json`
|
|
60
|
+
- Auto-shadowing the DB to `/tmp` when it lives on a network FS
|
|
95
61
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
Found graph.json (X hours old) — importing into monograph…
|
|
62
|
+
```bash
|
|
63
|
+
node "$SCRIPT" --dir "$DIR" --db "$DB" --no-llm
|
|
99
64
|
```
|
|
100
65
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
**Otherwise:**
|
|
105
|
-
Proceed to **Step 4: Run analysis**.
|
|
66
|
+
Wait for completion. Capture stdout. Note how many file nodes were found and how
|
|
67
|
+
many layers were detected. Do NOT advise the user about API keys.
|
|
106
68
|
|
|
107
69
|
---
|
|
108
70
|
|
|
109
|
-
## Step
|
|
71
|
+
## Step 3: Per-file summarization (ONLY if `--no-llm` and `--layers-only` are both UNSET)
|
|
110
72
|
|
|
111
|
-
|
|
73
|
+
This is where YOU (the current Claude session) do the LLM work. The script left
|
|
74
|
+
behind a fresh `.understand/knowledge-graph.json` with placeholder summaries.
|
|
112
75
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
```
|
|
76
|
+
1. Read `.understand/knowledge-graph.json`. For each node where `properties.fileSummary`
|
|
77
|
+
is empty or marked `[heuristic]`, do the following:
|
|
78
|
+
- Use the `Read` tool on `node.file_path` (relative to `$DIR`).
|
|
79
|
+
- Produce a JSON object: `{ id, fileSummary, tags, complexity, functionSummaries, classSummaries }`
|
|
80
|
+
where:
|
|
81
|
+
- `fileSummary`: 1-2 sentences explaining what the file does
|
|
82
|
+
- `tags`: array of 2-5 short tags
|
|
83
|
+
- `complexity`: "simple" | "moderate" | "complex"
|
|
84
|
+
- `functionSummaries`: top-5 functions → 1-sentence each
|
|
85
|
+
- `classSummaries`: classes → 1-sentence each
|
|
86
|
+
2. Process files in batches of 5 for efficiency. Use `--max-files` to cap if set.
|
|
87
|
+
3. Collect all analyses into an `analyses` array.
|
|
126
88
|
|
|
127
|
-
|
|
128
|
-
1. Read all file nodes from the monograph DB
|
|
129
|
-
2. Pick the best available LLM path automatically (no env vars to set):
|
|
130
|
-
- `claude -p` CLI passthrough — reuses the active Claude Code authentication
|
|
131
|
-
- direct Anthropic API — if `ANTHROPIC_API_KEY` happens to be set (faster for bulk runs)
|
|
132
|
-
- heuristic-only fallback — if neither is reachable
|
|
133
|
-
3. For each file, generate summaries, tags, and complexity
|
|
134
|
-
4. Detect architectural layers
|
|
135
|
-
5. Write enrichment data back to `monograph.db` (community_id + properties JSON)
|
|
136
|
-
6. Emit a `graph.json` to `$DIR/.understand/knowledge-graph.json`
|
|
137
|
-
|
|
138
|
-
Wait for the script to complete before proceeding. Do NOT pre-check or advise about
|
|
139
|
-
`ANTHROPIC_API_KEY` — the script picks its path silently and prints the chosen mode
|
|
140
|
-
on stdout. Report only what the script actually reports.
|
|
89
|
+
If `$ARGUMENTS` includes `--no-llm` or `--layers-only`, SKIP this step entirely.
|
|
141
90
|
|
|
142
91
|
---
|
|
143
92
|
|
|
144
|
-
## Step
|
|
93
|
+
## Step 4: Write analyses back to the DB
|
|
145
94
|
|
|
146
|
-
|
|
95
|
+
Pipe the collected analyses to a small re-import:
|
|
147
96
|
|
|
148
97
|
```bash
|
|
149
|
-
|
|
150
|
-
IMPORT_SCRIPT="$REPO_ROOT/scripts/ua-import.mjs"
|
|
151
|
-
# fallback: alongside understand-analyze.mjs
|
|
152
|
-
[ ! -f "$IMPORT_SCRIPT" ] && IMPORT_SCRIPT="$(dirname $SCRIPT)/../../../scripts/ua-import.mjs"
|
|
153
|
-
node "$IMPORT_SCRIPT" "$GRAPH_JSON" "$DB"
|
|
98
|
+
echo "$ANALYSES_JSON" | node "$SCRIPT" --dir "$DIR" --db "$DB" --import-analyses-stdin
|
|
154
99
|
```
|
|
155
100
|
|
|
156
|
-
If
|
|
101
|
+
(If your `analyses` array is empty, skip this step.)
|
|
157
102
|
|
|
158
103
|
---
|
|
159
104
|
|
|
160
|
-
## Step
|
|
161
|
-
|
|
162
|
-
After the analysis or import completes, show a summary:
|
|
105
|
+
## Step 5: Report
|
|
163
106
|
|
|
164
107
|
```
|
|
165
108
|
╔══════════════════════════════════════════════════╗
|
|
166
109
|
║ /monomind:understand — Enrichment Done ║
|
|
167
110
|
╠══════════════════════════════════════════════════╣
|
|
168
111
|
║ DB: .monomind/monograph.db ║
|
|
169
|
-
║
|
|
170
|
-
║
|
|
112
|
+
║ Files analyzed: <N> ║
|
|
113
|
+
║ LLM summaries: <N> (via active session) ║
|
|
114
|
+
║ Layers: <N> ║
|
|
171
115
|
║ graph.json: .understand/knowledge-graph.json║
|
|
172
116
|
╚══════════════════════════════════════════════════╝
|
|
173
117
|
```
|
|
174
118
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
>
|
|
119
|
+
If LLM summaries = 0 (because `--no-llm` was set), say "heuristic-only mode — no per-file summaries written".
|
|
120
|
+
|
|
121
|
+
Then:
|
|
122
|
+
> Open the Monomind control panel and click **Monograph → GRAPH** to see layers.
|
|
123
|
+
> Each color = one architectural layer (API, Service, Data, UI, etc.).
|
|
179
124
|
>
|
|
180
|
-
>
|
|
181
|
-
> - `/monomind:understand --full` —
|
|
182
|
-
> - `/monomind:understand --layers-only` — refresh only
|
|
183
|
-
> - `/monomind:understand --
|
|
184
|
-
> - `/monomind:understand --onboard` — generate an onboarding guide
|
|
125
|
+
> Follow-ups:
|
|
126
|
+
> - `/monomind:understand --full` — re-run from scratch
|
|
127
|
+
> - `/monomind:understand --layers-only` — refresh only layers
|
|
128
|
+
> - `/monomind:understand --no-llm` — heuristic-only mode
|
|
185
129
|
|
|
186
130
|
---
|
|
187
131
|
|
|
188
132
|
## Error Handling
|
|
189
133
|
|
|
190
|
-
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
-
|
|
194
|
-
- If monograph.db has no file nodes, tell the user to run `npx monomind monograph build` first.
|
|
195
|
-
- All errors are non-fatal to the main session — report and return cleanly.
|
|
134
|
+
- Do NOT prompt the user to set `ANTHROPIC_API_KEY`. LLM work happens in this session.
|
|
135
|
+
- If the script exits non-zero: show stderr and suggest `npm install -g monomind@latest`.
|
|
136
|
+
- If monograph.db has no file nodes: tell the user to run `npx monomind monograph build` first.
|
|
137
|
+
- All errors are non-fatal — report and return cleanly.
|
|
196
138
|
|
|
197
|
-
To
|
|
139
|
+
To re-run on a schedule: wrap with `/monomind:repeat`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monoes/monomindcli",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.24",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Monomind CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -129,60 +129,16 @@ function detectLayersHeuristic(fileNodes) {
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
// ── Anthropic API helpers ─────────────────────────────────────────────────────
|
|
132
|
-
//
|
|
133
|
-
//
|
|
134
|
-
//
|
|
135
|
-
//
|
|
136
|
-
//
|
|
132
|
+
// LLM enrichment requires ANTHROPIC_API_KEY. When the script is invoked from
|
|
133
|
+
// inside a Claude Code session via /monomind:understand, the slash command
|
|
134
|
+
// orchestrates the LLM work inline (using the active session) — the script
|
|
135
|
+
// itself runs in --no-llm heuristic mode in that flow. Attempting to spawn
|
|
136
|
+
// `claude -p` from a nested subprocess does NOT work (the nested CLI hangs
|
|
137
|
+
// indefinitely), so we no longer try that path.
|
|
137
138
|
const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
|
|
138
139
|
const ANTHROPIC_URL = 'https://api.anthropic.com/v1/messages';
|
|
139
140
|
const MODEL = 'claude-haiku-4-5-20251001'; // cheapest for bulk analysis
|
|
140
141
|
|
|
141
|
-
// Detect `claude` CLI once at startup.
|
|
142
|
-
let _claudeCliPath = null;
|
|
143
|
-
function _detectClaudeCli() {
|
|
144
|
-
if (_claudeCliPath !== null) return _claudeCliPath;
|
|
145
|
-
try {
|
|
146
|
-
const out = execSync('command -v claude 2>/dev/null', { encoding: 'utf-8' }).trim();
|
|
147
|
-
_claudeCliPath = out || '';
|
|
148
|
-
} catch { _claudeCliPath = ''; }
|
|
149
|
-
return _claudeCliPath;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const USE_CLAUDE_CLI = !ANTHROPIC_API_KEY && !!_detectClaudeCli();
|
|
153
|
-
|
|
154
|
-
async function callClaudeViaCli(systemPrompt, userPrompt, maxTokens = 1024) {
|
|
155
|
-
return new Promise((resolveP, reject) => {
|
|
156
|
-
// NOTE: do NOT pass --bare here. --bare disables OAuth/keychain reads
|
|
157
|
-
// and forces ANTHROPIC_API_KEY — which is exactly what we're avoiding.
|
|
158
|
-
// We want the CLI to use the user's logged-in Claude Code session.
|
|
159
|
-
const args = [
|
|
160
|
-
'-p',
|
|
161
|
-
'--model', 'haiku',
|
|
162
|
-
'--output-format', 'text',
|
|
163
|
-
'--disable-slash-commands', // skip skill auto-resolution overhead
|
|
164
|
-
`${systemPrompt}\n\n---\n\n${userPrompt}`,
|
|
165
|
-
];
|
|
166
|
-
const child = spawn(_claudeCliPath, args, {
|
|
167
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
168
|
-
env: { ...process.env },
|
|
169
|
-
});
|
|
170
|
-
let out = '', err = '';
|
|
171
|
-
child.stdout.on('data', d => out += d.toString());
|
|
172
|
-
child.stderr.on('data', d => err += d.toString());
|
|
173
|
-
const timeout = setTimeout(() => {
|
|
174
|
-
child.kill('SIGKILL');
|
|
175
|
-
reject(new Error('claude -p timed out after 120s'));
|
|
176
|
-
}, 120000);
|
|
177
|
-
child.on('close', code => {
|
|
178
|
-
clearTimeout(timeout);
|
|
179
|
-
if (code !== 0) return reject(new Error(`claude -p exited ${code}: ${err.slice(0, 200)}`));
|
|
180
|
-
resolveP(out.trim());
|
|
181
|
-
});
|
|
182
|
-
child.on('error', e => { clearTimeout(timeout); reject(e); });
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
142
|
async function callClaudeViaApi(systemPrompt, userPrompt, maxTokens = 1024) {
|
|
187
143
|
const body = JSON.stringify({
|
|
188
144
|
model: MODEL,
|
|
@@ -225,10 +181,7 @@ async function callClaude(systemPrompt, userPrompt, maxTokens = 1024) {
|
|
|
225
181
|
if (ANTHROPIC_API_KEY) {
|
|
226
182
|
return callClaudeViaApi(systemPrompt, userPrompt, maxTokens);
|
|
227
183
|
}
|
|
228
|
-
|
|
229
|
-
return callClaudeViaCli(systemPrompt, userPrompt, maxTokens);
|
|
230
|
-
}
|
|
231
|
-
throw new Error('No LLM path available: set ANTHROPIC_API_KEY or install `claude` CLI');
|
|
184
|
+
throw new Error('No LLM path available: set ANTHROPIC_API_KEY (or use the /monomind:understand slash command, which orchestrates LLM work via the active Claude Code session)');
|
|
232
185
|
}
|
|
233
186
|
|
|
234
187
|
function parseJson(text) {
|
|
@@ -632,10 +585,36 @@ async function main() {
|
|
|
632
585
|
process.exit(1);
|
|
633
586
|
}
|
|
634
587
|
|
|
588
|
+
// Detect non-local filesystems where better-sqlite3 can't acquire file locks
|
|
589
|
+
// (NFS, SMB, FUSE volumes — typically /Volumes/* on macOS or /mnt/* on Linux).
|
|
590
|
+
// When detected, copy the DB to /tmp, work there, copy back atomically at end.
|
|
591
|
+
let workingDbPath = dbPathArg;
|
|
592
|
+
let dbWasShadowed = false;
|
|
593
|
+
let originalDbPath = dbPathArg;
|
|
594
|
+
const isNetworkFs = /^\/Volumes\//.test(dbPathArg) ||
|
|
595
|
+
/^\/mnt\//.test(dbPathArg) ||
|
|
596
|
+
/^\/media\//.test(dbPathArg) ||
|
|
597
|
+
/^\\\\/.test(dbPathArg); // UNC paths on Windows
|
|
598
|
+
if (isNetworkFs && !dryRun) {
|
|
599
|
+
const os = await import('node:os');
|
|
600
|
+
const crypto = await import('node:crypto');
|
|
601
|
+
const tmpName = 'monograph-work-' + crypto.randomBytes(6).toString('hex') + '.db';
|
|
602
|
+
workingDbPath = join(os.tmpdir(), tmpName);
|
|
603
|
+
try {
|
|
604
|
+
console.log(`[understand] DB is on a non-local filesystem (${dbPathArg}). Copying to ${workingDbPath} to avoid SQLite lock issues...`);
|
|
605
|
+
const { copyFileSync } = await import('node:fs');
|
|
606
|
+
copyFileSync(originalDbPath, workingDbPath);
|
|
607
|
+
dbWasShadowed = true;
|
|
608
|
+
} catch (e) {
|
|
609
|
+
console.warn(`[understand] Could not copy to /tmp (${e.message}). Trying in place...`);
|
|
610
|
+
workingDbPath = dbPathArg;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
635
614
|
// Retry openDb against SQLite BUSY when monograph is building in the background
|
|
636
615
|
let db;
|
|
637
616
|
for (let attempt = 0; attempt < 5; attempt++) {
|
|
638
|
-
try { db = mg.openDb(
|
|
617
|
+
try { db = mg.openDb(workingDbPath); break; }
|
|
639
618
|
catch (e) {
|
|
640
619
|
if (attempt === 4) throw e;
|
|
641
620
|
const msg = String(e?.message || e);
|
|
@@ -699,22 +678,19 @@ async function main() {
|
|
|
699
678
|
const batch = toAnalyze.slice(0, limit);
|
|
700
679
|
console.log(`[understand] Analyzing ${batch.length} files (${toAnalyze.length - batch.length} skipped/already enriched)`);
|
|
701
680
|
|
|
702
|
-
//
|
|
703
|
-
//
|
|
704
|
-
//
|
|
705
|
-
//
|
|
706
|
-
|
|
707
|
-
const llmPath =
|
|
708
|
-
: USE_CLAUDE_CLI ? 'claude-cli'
|
|
709
|
-
: ANTHROPIC_API_KEY ? 'api'
|
|
710
|
-
: 'none';
|
|
681
|
+
// LLM path: direct Anthropic API only. The script does NOT try to spawn
|
|
682
|
+
// `claude -p` from within Claude Code subprocesses — that hangs because
|
|
683
|
+
// nested CLI sessions aren't supported. For LLM enrichment without an API
|
|
684
|
+
// key, use the /monomind:understand slash command which orchestrates LLM
|
|
685
|
+
// work via the active Claude Code session inline.
|
|
686
|
+
const llmPath = ANTHROPIC_API_KEY ? 'api' : 'none';
|
|
711
687
|
if (llmPath === 'none' && !noLlm) {
|
|
712
|
-
console.
|
|
713
|
-
console.
|
|
714
|
-
|
|
715
|
-
console.log('[understand]
|
|
688
|
+
console.log('[understand] No ANTHROPIC_API_KEY — running in heuristic mode for layer detection.');
|
|
689
|
+
console.log('[understand] For per-file summaries: either set ANTHROPIC_API_KEY for direct API,');
|
|
690
|
+
console.log('[understand] or use the /monomind:understand slash command from inside Claude Code');
|
|
691
|
+
console.log('[understand] (the slash command does inline analysis via the active session, no key needed).');
|
|
716
692
|
} else if (llmPath === 'api' && !noLlm) {
|
|
717
|
-
console.log('[understand] LLM path: direct Anthropic API
|
|
693
|
+
console.log('[understand] LLM path: direct Anthropic API');
|
|
718
694
|
}
|
|
719
695
|
const useLlm = !noLlm && llmPath !== 'none';
|
|
720
696
|
|
|
@@ -863,13 +839,27 @@ async function main() {
|
|
|
863
839
|
console.log(`║ ONBOARDING.md: ${relative(CWD, onboardOut).padEnd(31)}║`);
|
|
864
840
|
}
|
|
865
841
|
console.log('╚══════════════════════════════════════════════════╝');
|
|
842
|
+
|
|
843
|
+
// Copy DB back if we shadowed it on /tmp due to network FS
|
|
844
|
+
if (dbWasShadowed && !dryRun) {
|
|
845
|
+
try {
|
|
846
|
+
const { copyFileSync, unlinkSync } = await import('node:fs');
|
|
847
|
+
try { db.close(); } catch {}
|
|
848
|
+
console.log(`[understand] Copying enriched DB back to ${originalDbPath}...`);
|
|
849
|
+
copyFileSync(workingDbPath, originalDbPath);
|
|
850
|
+
try { unlinkSync(workingDbPath); } catch {}
|
|
851
|
+
} catch (e) {
|
|
852
|
+
console.error(`[understand] Failed to copy DB back: ${e.message}`);
|
|
853
|
+
console.error(`[understand] Enriched DB is at ${workingDbPath} — copy manually if needed.`);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
866
856
|
}
|
|
867
857
|
|
|
868
858
|
// ── Detect layers and write communities to DB ────────────────────────────────
|
|
869
859
|
async function detectAndWriteLayers(db, fileNodes, forceHeuristic, dryRun, dir) {
|
|
870
860
|
let layers;
|
|
871
861
|
|
|
872
|
-
if (!forceHeuristic &&
|
|
862
|
+
if (!forceHeuristic && ANTHROPIC_API_KEY) {
|
|
873
863
|
console.log('[understand] Detecting architectural layers via LLM...');
|
|
874
864
|
const filePaths = fileNodes.map(n => n.file_path).filter(Boolean);
|
|
875
865
|
try {
|