getprismo 0.1.6 → 0.1.7
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 +6 -6
- package/lib/prismo-dev/context-optimize.js +122 -12
- package/lib/prismo-dev/fixes.js +6 -4
- package/lib/prismo-dev/report.js +4 -2
- package/lib/prismo-dev/scan.js +0 -2
- package/lib/prismo-dev-scan.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -68,8 +68,8 @@ Fixed:
|
|
|
68
68
|
- Created .cursorignore
|
|
69
69
|
- Generated prismo-dev-report.md
|
|
70
70
|
- Generated .prismo/architecture-summary.md
|
|
71
|
-
- Generated .prismo/recommended-CLAUDE.md
|
|
72
|
-
- Generated .prismo/recommended-AGENTS.md
|
|
71
|
+
- Generated .prismo/recommended-CLAUDE.boilerplate.md
|
|
72
|
+
- Generated .prismo/recommended-AGENTS.boilerplate.md
|
|
73
73
|
- Generated .prismo/recommended-.claudeignore
|
|
74
74
|
- Generated .prismo/recommended-.cursorignore
|
|
75
75
|
- Generated .prismo/recommended-.gitignore-additions
|
|
@@ -384,8 +384,8 @@ what doctor creates:
|
|
|
384
384
|
.prismo/architecture-summary.md compact project overview for agents
|
|
385
385
|
.prismo/backend-summary.md backend-specific context
|
|
386
386
|
.prismo/frontend-summary.md frontend-specific context
|
|
387
|
-
.prismo/recommended-CLAUDE.md
|
|
388
|
-
.prismo/recommended-AGENTS.md
|
|
387
|
+
.prismo/recommended-CLAUDE.boilerplate.md CLAUDE.md boilerplate reference; do not overwrite curated files
|
|
388
|
+
.prismo/recommended-AGENTS.boilerplate.md AGENTS.md boilerplate reference; do not overwrite curated files
|
|
389
389
|
.prismo/recommended-.claudeignore full recommended ignore list
|
|
390
390
|
.prismo/recommended-.cursorignore full recommended ignore list
|
|
391
391
|
.prismo/recommended-.gitignore-additions things your gitignore might be missing
|
|
@@ -600,8 +600,8 @@ no api keys. no intercepted prompts. no data uploaded.
|
|
|
600
600
|
├── frontend-summary.md
|
|
601
601
|
├── frontend-context.md
|
|
602
602
|
├── backend-context.md
|
|
603
|
-
├── recommended-CLAUDE.md
|
|
604
|
-
├── recommended-AGENTS.md
|
|
603
|
+
├── recommended-CLAUDE.boilerplate.md
|
|
604
|
+
├── recommended-AGENTS.boilerplate.md
|
|
605
605
|
├── recommended-.claudeignore
|
|
606
606
|
├── recommended-.cursorignore
|
|
607
607
|
├── recommended-.gitignore-additions
|
|
@@ -122,18 +122,49 @@ function isNonSourcePath(rel) {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
function detectBackendPaths(result) {
|
|
125
|
-
const
|
|
126
|
-
const
|
|
127
|
-
const
|
|
128
|
-
const
|
|
129
|
-
const
|
|
130
|
-
|
|
125
|
+
const pythonText = (file) => readIfText(path.join(result.root, file.path), 256 * 1024) || "";
|
|
126
|
+
const isRootPython = (rel) => /^[^/]+\.py$/.test(rel);
|
|
127
|
+
const isPython = (rel) => rel.endsWith(".py");
|
|
128
|
+
const hasFastApiSignal = (file) => /FastAPI\s*\(|APIRouter\s*\(|@app\.(get|post|put|patch|delete)|@router\.(get|post|put|patch|delete)/.test(pythonText(file));
|
|
129
|
+
const api = findRepoFiles(result, (rel, file) => !isNonSourcePath(rel) && (
|
|
130
|
+
/(backend|app|src)\/.*(router|routes|api)\//.test(rel) ||
|
|
131
|
+
/(backend|app|src)\/.*(router|routes).*\.py$/.test(rel) ||
|
|
132
|
+
/\/(routing|routers?)\.py$/.test(rel) ||
|
|
133
|
+
(isRootPython(rel) && hasFastApiSignal(file))
|
|
134
|
+
), 30).map((f) => f.path);
|
|
135
|
+
const services = findRepoFiles(result, (rel) => !isNonSourcePath(rel) && (
|
|
136
|
+
/(backend|app|src)\/.*(service|services|application)/.test(rel) ||
|
|
137
|
+
/\/applications?\.py$/.test(rel) ||
|
|
138
|
+
(isRootPython(rel) && /(service|worker|manager|client|heartbeat|memory|chat|tool|orchestrator|pipeline)/i.test(rel))
|
|
139
|
+
), 40).map((f) => f.path);
|
|
140
|
+
const models = findRepoFiles(result, (rel) => !isNonSourcePath(rel) && (
|
|
141
|
+
/(backend|app|src)\/.*models\.py$/.test(rel) ||
|
|
142
|
+
/(backend|app|src)\/.*schema/.test(rel) ||
|
|
143
|
+
/\/models\.py$/.test(rel) ||
|
|
144
|
+
(isRootPython(rel) && /(model|schema|entity|types?)/i.test(rel))
|
|
145
|
+
), 30).map((f) => f.path);
|
|
146
|
+
const db = findRepoFiles(result, (rel) => !isNonSourcePath(rel) && (
|
|
147
|
+
/(backend|app|src)\/.*\/(db|database|alembic|migrations)[/.]/.test(rel) ||
|
|
148
|
+
(isPython(rel) && /(sqlite|qdrant|neo4j|database|storage|repository|vector|graph|migration)/i.test(rel))
|
|
149
|
+
), 30).map((f) => f.path);
|
|
150
|
+
const config = findRepoFiles(result, (rel) => !isNonSourcePath(rel) && (
|
|
151
|
+
/(backend|app|src)\/.*(config|settings|env).*\.py$/.test(rel) ||
|
|
152
|
+
(isRootPython(rel) && /(config|settings|env)/i.test(rel)) ||
|
|
153
|
+
rel.endsWith("requirements.txt") ||
|
|
154
|
+
rel === "pyproject.toml"
|
|
155
|
+
), 20).map((f) => f.path);
|
|
156
|
+
const auth = findRepoFiles(result, (rel, file) => !isNonSourcePath(rel) && (
|
|
157
|
+
/(backend|app|src)\/.*auth/.test(rel) ||
|
|
158
|
+
/\/security\.py$/.test(rel) ||
|
|
159
|
+
(isPython(rel) && /(auth|security|permission|token|session|oauth|jwt|middleware)/i.test(rel)) ||
|
|
160
|
+
(isRootPython(rel) && /(Depends|HTTPBearer|OAuth2|JWT|Authorization)/.test(pythonText(file)))
|
|
161
|
+
), 30).map((f) => f.path);
|
|
131
162
|
return { api, services, models, db, config, auth };
|
|
132
163
|
}
|
|
133
164
|
|
|
134
165
|
function detectFrontendPaths(result) {
|
|
135
166
|
return {
|
|
136
|
-
app: findRepoFiles(result, (rel) => !isNonSourcePath(rel) && (/frontend\/src\/app\//.test(rel) || /src\/app\//.test(rel) || /apps\/[^/]+\/app\//.test(rel) || /apps\/[^/]+\/src\/app\//.test(rel)), 24).map((f) => f.path),
|
|
167
|
+
app: findRepoFiles(result, (rel) => !isNonSourcePath(rel) && (/frontend\/src\/app\//.test(rel) || /frontend\/src\/App\.[jt]sx?$/.test(rel) || /src\/App\.[jt]sx?$/.test(rel) || /src\/app\//.test(rel) || /apps\/[^/]+\/app\//.test(rel) || /apps\/[^/]+\/src\/app\//.test(rel)), 24).map((f) => f.path),
|
|
137
168
|
components: findRepoFiles(result, (rel) => !isNonSourcePath(rel) && (/frontend\/src\/components\//.test(rel) || /src\/components\//.test(rel) || /apps\/[^/]+\/.*components\//.test(rel) || /packages\/[^/]+\/.*components\//.test(rel)), 20).map((f) => f.path),
|
|
138
169
|
apiClient: findRepoFiles(result, (rel) => !isNonSourcePath(rel) && (/frontend\/src\/(lib|hooks)\/.*(api|client|query|finops)/.test(rel) || /src\/(lib|hooks)\/.*(api|client|query)/.test(rel)), 20).map((f) => f.path),
|
|
139
170
|
styling: findRepoFiles(result, (rel) => !isNonSourcePath(rel) && (/tailwind\.config|globals\.css|\.module\.css|frontend\/src\/app\/globals/.test(rel)), 20).map((f) => f.path),
|
|
@@ -186,6 +217,60 @@ function mdList(items, empty = "None detected.") {
|
|
|
186
217
|
return items.map((item) => `- \`${item}\``).join("\n");
|
|
187
218
|
}
|
|
188
219
|
|
|
220
|
+
function topBySize(files, limit = 8) {
|
|
221
|
+
return [...(files || [])]
|
|
222
|
+
.filter((file) => !file.ignored && file.kind !== "binary")
|
|
223
|
+
.sort((a, b) => b.size - a.size)
|
|
224
|
+
.slice(0, limit)
|
|
225
|
+
.map((file) => `${file.path} (${formatBytes(file.size)})`);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function inferGaps(ctx) {
|
|
229
|
+
const gaps = [];
|
|
230
|
+
if (ctx.backendDetected && !ctx.backend.api.length) {
|
|
231
|
+
gaps.push("No conventional backend API layout detected; review root-level Python files or custom service modules for FastAPI/APIRouter usage.");
|
|
232
|
+
}
|
|
233
|
+
if (ctx.backendDetected && !ctx.backend.services.length) {
|
|
234
|
+
gaps.push("No conventional service directory detected; backend services may use flat files or project-specific naming.");
|
|
235
|
+
}
|
|
236
|
+
if (ctx.frontendDetected && !ctx.frontend.app.length) {
|
|
237
|
+
gaps.push("No conventional frontend routing surface detected; Vite/React routes may live in App.tsx or custom tab components.");
|
|
238
|
+
}
|
|
239
|
+
return gaps;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function summarizeRiskyDirectories(dirs) {
|
|
243
|
+
const groups = new Map();
|
|
244
|
+
for (const dir of dirs || []) {
|
|
245
|
+
const normalized = dir.path.replace(/\\/g, "/");
|
|
246
|
+
const parts = normalized.split("/");
|
|
247
|
+
let key = `${normalized}/`;
|
|
248
|
+
if (parts.includes("__pycache__")) {
|
|
249
|
+
const before = parts.slice(0, parts.indexOf("__pycache__"));
|
|
250
|
+
const prefix = before.length ? `${before[0]}/**` : "**";
|
|
251
|
+
key = `${prefix}/__pycache__/`;
|
|
252
|
+
} else if (parts.includes("node_modules")) {
|
|
253
|
+
key = `${parts.slice(0, parts.indexOf("node_modules") + 1).join("/")}/**`;
|
|
254
|
+
} else if (parts.length > 2) {
|
|
255
|
+
key = `${parts.slice(0, 2).join("/")}/**/${parts[parts.length - 1]}/`;
|
|
256
|
+
}
|
|
257
|
+
const existing = groups.get(key) || { key, count: 0, exposed: 0, ignored: 0, examples: [] };
|
|
258
|
+
existing.count += 1;
|
|
259
|
+
if (dir.exposed) existing.exposed += 1;
|
|
260
|
+
else existing.ignored += 1;
|
|
261
|
+
if (existing.examples.length < 2) existing.examples.push(`${normalized}/`);
|
|
262
|
+
groups.set(key, existing);
|
|
263
|
+
}
|
|
264
|
+
return Array.from(groups.values())
|
|
265
|
+
.sort((a, b) => b.exposed - a.exposed || b.count - a.count)
|
|
266
|
+
.slice(0, 25)
|
|
267
|
+
.map((group) => {
|
|
268
|
+
const state = group.exposed ? `${group.exposed} exposed` : `${group.ignored} ignored`;
|
|
269
|
+
const example = group.examples[0] && group.examples[0] !== group.key ? `; e.g. ${group.examples[0]}` : "";
|
|
270
|
+
return `${group.key} (${group.count} director${group.count === 1 ? "y" : "ies"}, ${state}${example})`;
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
|
|
189
274
|
function proseList(items, empty = "none detected") {
|
|
190
275
|
return items && items.length ? items.join(", ") : empty;
|
|
191
276
|
}
|
|
@@ -194,6 +279,7 @@ function renderArchitectureSummary(ctx) {
|
|
|
194
279
|
const apiLayer = ctx.backend.api.slice(0, 6);
|
|
195
280
|
const dbLayer = ctx.backend.db.slice(0, 6);
|
|
196
281
|
const frontendLayer = ctx.frontend.app.slice(0, 6);
|
|
282
|
+
const gaps = inferGaps(ctx);
|
|
197
283
|
const readOrder = [
|
|
198
284
|
"- Start here.",
|
|
199
285
|
ctx.backendDetected ? "- For backend work, read `.prismo/backend-summary.md` next." : null,
|
|
@@ -234,6 +320,10 @@ function renderArchitectureSummary(ctx) {
|
|
|
234
320
|
"",
|
|
235
321
|
ctx.warnings.length ? ctx.warnings.map((warning) => `- ${warning}`).join("\n") : "- No major local context risks detected.",
|
|
236
322
|
"",
|
|
323
|
+
"## Detection Gaps",
|
|
324
|
+
"",
|
|
325
|
+
gaps.length ? gaps.map((gap) => `- ${gap}`).join("\n") : "- No major architecture-detection gaps surfaced.",
|
|
326
|
+
"",
|
|
237
327
|
"## AI Workflow Notes",
|
|
238
328
|
"",
|
|
239
329
|
"- Prefer this summary before broad repo reads.",
|
|
@@ -244,6 +334,7 @@ function renderArchitectureSummary(ctx) {
|
|
|
244
334
|
}
|
|
245
335
|
|
|
246
336
|
function renderBackendSummary(ctx) {
|
|
337
|
+
const backendCandidates = topBySize(ctx.scan.files.filter((file) => file.path.endsWith(".py") && !isNonSourcePath(file.path)), 8);
|
|
247
338
|
return [
|
|
248
339
|
"# Backend Summary",
|
|
249
340
|
"",
|
|
@@ -273,10 +364,21 @@ function renderBackendSummary(ctx) {
|
|
|
273
364
|
"",
|
|
274
365
|
mdList(ctx.backend.config),
|
|
275
366
|
"",
|
|
367
|
+
"## Load-Bearing Candidates",
|
|
368
|
+
"",
|
|
369
|
+
mdList(backendCandidates, "No Python source candidates detected."),
|
|
370
|
+
"",
|
|
371
|
+
"## Detection Notes",
|
|
372
|
+
"",
|
|
373
|
+
ctx.backend.api.length || ctx.backend.services.length
|
|
374
|
+
? "- Backend paths were inferred from conventional directories plus root-level Python/FastAPI/service filename signals."
|
|
375
|
+
: "- No conventional backend paths were detected; inspect root-level Python modules and custom service naming manually.",
|
|
376
|
+
"",
|
|
276
377
|
].join("\n");
|
|
277
378
|
}
|
|
278
379
|
|
|
279
380
|
function renderFrontendSummary(ctx) {
|
|
381
|
+
const frontendCandidates = topBySize(ctx.scan.files.filter((file) => /\.(tsx?|jsx?)$/.test(file.path) && /(^|\/)(frontend|src|app|components|hooks)\//.test(file.path)), 8);
|
|
280
382
|
return [
|
|
281
383
|
"# Frontend Summary",
|
|
282
384
|
"",
|
|
@@ -302,6 +404,10 @@ function renderFrontendSummary(ctx) {
|
|
|
302
404
|
"",
|
|
303
405
|
mdList(ctx.frontend.styling),
|
|
304
406
|
"",
|
|
407
|
+
"## Load-Bearing Candidates",
|
|
408
|
+
"",
|
|
409
|
+
mdList(frontendCandidates, "No frontend source candidates detected."),
|
|
410
|
+
"",
|
|
305
411
|
].join("\n");
|
|
306
412
|
}
|
|
307
413
|
|
|
@@ -319,7 +425,9 @@ function renderRecommendedClaude(ctx) {
|
|
|
319
425
|
if (hasPath(ctx.scan, (rel) => rel === "frontend/package.json")) commands.push("cd frontend && npm run test");
|
|
320
426
|
if (hasPath(ctx.scan, (rel) => rel === "backend/pytest.ini" || rel.startsWith("backend/tests/"))) commands.push("cd backend && pytest");
|
|
321
427
|
return [
|
|
322
|
-
"# CLAUDE.md",
|
|
428
|
+
"# CLAUDE.md Boilerplate",
|
|
429
|
+
"",
|
|
430
|
+
"Do not overwrite an existing curated CLAUDE.md with this file. Use it as a diff/reference for missing compact-context guidance only.",
|
|
323
431
|
"",
|
|
324
432
|
"Keep context small. Start with `.prismo/architecture-summary.md`; use scoped `.prismo/*-summary.md` files only when relevant.",
|
|
325
433
|
"",
|
|
@@ -351,7 +459,9 @@ function renderRecommendedClaude(ctx) {
|
|
|
351
459
|
|
|
352
460
|
function renderRecommendedAgents(ctx) {
|
|
353
461
|
return [
|
|
354
|
-
"# AGENTS.md",
|
|
462
|
+
"# AGENTS.md Boilerplate",
|
|
463
|
+
"",
|
|
464
|
+
"Do not overwrite an existing curated AGENTS.md with this file. Use it as a diff/reference for missing compact-context guidance only.",
|
|
355
465
|
"",
|
|
356
466
|
"Use `.prismo/architecture-summary.md` first to avoid repeated broad repo exploration. Keep this file durable and short; task-specific details belong in the prompt or scoped context files.",
|
|
357
467
|
"",
|
|
@@ -413,7 +523,7 @@ function renderOptimizeReport(ctx, generatedFiles) {
|
|
|
413
523
|
"",
|
|
414
524
|
"## Token-Heavy Directories",
|
|
415
525
|
"",
|
|
416
|
-
mdList(ctx.scan.highRiskDirs
|
|
526
|
+
mdList(summarizeRiskyDirectories(ctx.scan.highRiskDirs)),
|
|
417
527
|
"",
|
|
418
528
|
"## Optimization Suggestions",
|
|
419
529
|
"",
|
|
@@ -530,8 +640,8 @@ function renderContextCommand(ctx, scope = null) {
|
|
|
530
640
|
function getOptimizePendingFiles(ctx) {
|
|
531
641
|
const pending = [
|
|
532
642
|
["architecture-summary.md", renderArchitectureSummary(ctx)],
|
|
533
|
-
["recommended-CLAUDE.md", renderRecommendedClaude(ctx)],
|
|
534
|
-
["recommended-AGENTS.md", renderRecommendedAgents(ctx)],
|
|
643
|
+
["recommended-CLAUDE.boilerplate.md", renderRecommendedClaude(ctx)],
|
|
644
|
+
["recommended-AGENTS.boilerplate.md", renderRecommendedAgents(ctx)],
|
|
535
645
|
["recommended-.claudeignore", `${ctx.scan.recommendedClaudeIgnore.join("\n")}\n`],
|
|
536
646
|
["recommended-.cursorignore", `${ctx.scan.recommendedCursorIgnore.join("\n")}\n`],
|
|
537
647
|
["recommended-.gitignore-additions", renderGitignoreAdditions(ctx)],
|
package/lib/prismo-dev/fixes.js
CHANGED
|
@@ -77,8 +77,8 @@ function applyFixes(result, options = {}) {
|
|
|
77
77
|
}
|
|
78
78
|
if (ignoresOnly) return actions;
|
|
79
79
|
|
|
80
|
-
const report = options.dryRun ? { reportPath: path.join(result.root, "prismo-dev-report.md"), backupPath: null } : writeReport(result);
|
|
81
|
-
actions.push(`${options.dryRun ? "Would generate" : "Generated"}
|
|
80
|
+
const report = options.dryRun ? { reportPath: path.join(result.root, ".prismo", "prismo-dev-report.md"), backupPath: null } : writeReport(result);
|
|
81
|
+
actions.push(`${options.dryRun ? "Would generate" : "Generated"} .prismo/${path.basename(report.reportPath)}`);
|
|
82
82
|
if (report.backupPath) actions.push(`Backed up existing report to ${path.basename(report.backupPath)}`);
|
|
83
83
|
|
|
84
84
|
const claudeFile = result.instructionFiles.find((file) => file.isClaude);
|
|
@@ -92,10 +92,12 @@ function applyFixes(result, options = {}) {
|
|
|
92
92
|
|
|
93
93
|
const hasCodexRisk = result.issues.some((issue) => issue.category === "codex_config");
|
|
94
94
|
if (hasCodexRisk || result.instructionFiles.some((file) => file.path === "AGENTS.md" || file.path.startsWith(".codex/"))) {
|
|
95
|
-
const
|
|
95
|
+
const prismoDir = path.join(result.root, ".prismo");
|
|
96
|
+
if (!options.dryRun) fs.mkdirSync(prismoDir, { recursive: true });
|
|
97
|
+
const codexPath = path.join(prismoDir, "prismo-AGENTS-recommendations.md");
|
|
96
98
|
const backupPath = options.dryRun ? null : backupIfExists(codexPath);
|
|
97
99
|
if (!options.dryRun) fs.writeFileSync(codexPath, renderAgentsRecommendations(result), "utf8");
|
|
98
|
-
actions.push(`${options.dryRun ? "Would generate" : "Generated"} prismo-AGENTS-recommendations.md`);
|
|
100
|
+
actions.push(`${options.dryRun ? "Would generate" : "Generated"} .prismo/prismo-AGENTS-recommendations.md`);
|
|
99
101
|
if (backupPath) actions.push(`Backed up existing AGENTS recommendations to ${path.basename(backupPath)}`);
|
|
100
102
|
}
|
|
101
103
|
return actions;
|
package/lib/prismo-dev/report.js
CHANGED
|
@@ -94,7 +94,7 @@ function renderTerminalReport(result, options = {}) {
|
|
|
94
94
|
? "No matching local usage sessions were found; repo-risk estimates remain heuristic."
|
|
95
95
|
: "Potential savings estimates are heuristic and local-only, not provider billing data.");
|
|
96
96
|
lines.push("");
|
|
97
|
-
lines.push(reportEnabled ? "Report: prismo-dev-report.md" : "Report: skipped (--no-report)");
|
|
97
|
+
lines.push(reportEnabled ? "Report: .prismo/prismo-dev-report.md" : "Report: skipped (--no-report)");
|
|
98
98
|
return lines.join("\n");
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -342,7 +342,9 @@ function backupIfExists(filePath) {
|
|
|
342
342
|
}
|
|
343
343
|
|
|
344
344
|
function writeReport(result) {
|
|
345
|
-
const
|
|
345
|
+
const prismoDir = path.join(result.root, ".prismo");
|
|
346
|
+
fs.mkdirSync(prismoDir, { recursive: true });
|
|
347
|
+
const reportPath = path.join(prismoDir, "prismo-dev-report.md");
|
|
346
348
|
const backupPath = backupIfExists(reportPath);
|
|
347
349
|
fs.writeFileSync(reportPath, renderMarkdownReport(result), "utf8");
|
|
348
350
|
return { reportPath, backupPath };
|
package/lib/prismo-dev/scan.js
CHANGED
|
@@ -1060,9 +1060,7 @@ function scanRepo(rootDir = process.cwd(), options = {}) {
|
|
|
1060
1060
|
const recommendedCursorIgnore = Array.from(new Set([
|
|
1061
1061
|
...recommendedClaudeIgnore,
|
|
1062
1062
|
".prismo/",
|
|
1063
|
-
"prismo-dev-report.md",
|
|
1064
1063
|
"prismo-optimized-CLAUDE.template.md",
|
|
1065
|
-
"prismo-AGENTS-recommendations.md",
|
|
1066
1064
|
]));
|
|
1067
1065
|
const recommendations = buildRecommendations({
|
|
1068
1066
|
hasClaudeIgnore,
|
package/lib/prismo-dev-scan.js
CHANGED
|
@@ -304,7 +304,7 @@ Options:
|
|
|
304
304
|
--json Output valid JSON only for CI or future dashboard ingestion.
|
|
305
305
|
--usage Include real local Codex/Claude Code session usage in scan diagnostics.
|
|
306
306
|
--simple Print a plain-English scan summary for first-time or non-technical users.
|
|
307
|
-
--no-report Do not write prismo-dev-report.md.
|
|
307
|
+
--no-report Do not write .prismo/prismo-dev-report.md.
|
|
308
308
|
--limit N Number of recent local sessions to show.
|
|
309
309
|
--interval N Refresh interval in seconds for watch mode.
|
|
310
310
|
--dry-run Preview doctor/fix actions without writing files.
|
package/package.json
CHANGED