getprismo 0.1.20 → 0.1.21

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 CHANGED
@@ -146,6 +146,42 @@ watch caught lockfiles entering context, a file being read 286 times, and tool o
146
146
 
147
147
  ---
148
148
 
149
+ ## new: optimizer fit
150
+
151
+ not every token optimizer solves the same bottleneck. before stacking compression proxies, repo packers, code indexes, and MCP tools, run:
152
+
153
+ ```bash
154
+ npx getprismo scan --optimizer-fit
155
+ ```
156
+
157
+ PrismoDev scores your actual repo/session signals and recommends the right path:
158
+
159
+ ```text
160
+ Prismo Optimizer Fit
161
+
162
+ Primary bottleneck: Generated artifacts / ignore cleanup: HIGH
163
+
164
+ Bottlenecks
165
+ - Generated artifacts / ignore cleanup: High
166
+ .claudeignore is missing
167
+ - Oversized command/tool output: Medium
168
+ 237k tool/output tokens found in local sessions
169
+ - Repeated source exploration: Low
170
+ Repo/source exploration does not look like the main bottleneck
171
+
172
+ Recommended Stack
173
+ 1. Apply safe ignore/context fixes first.
174
+ Run: npx getprismo doctor --apply-suggestions --dry-run
175
+ Category: ignore cleanup (.claudeignore, .cursorignore)
176
+ 2. Sandbox noisy command output before adding more code-indexing tools.
177
+ Run: npx getprismo shield -- <noisy command>
178
+ Category: output sandboxing (Prismo shield, context-mode, RTK, tokf, distill)
179
+ ```
180
+
181
+ This makes PrismoDev the measure-first layer: it tells you whether you need ignore cleanup, output sandboxing, code indexing, repo packing, instruction trimming, session splitting, or MCP/tool hygiene.
182
+
183
+ ---
184
+
149
185
  ## new: context shield
150
186
 
151
187
  if you know a command may dump huge output, run it through prismo:
@@ -543,6 +579,7 @@ no install needed. npx runs it directly.
543
579
  | `cc` | claude code cost breakdown |
544
580
  | `cc timeline` | session reconstruction with events |
545
581
  | `scan --usage` | full repo scan with local usage data |
582
+ | `scan --optimizer-fit` | recommend which token-optimization path fits your repo/session |
546
583
  | `scan --simple` | plain-english summary |
547
584
  | `scan --fix` | create safe fix files |
548
585
  | `scan --ci` | fail CI when token-risk gates fail |
@@ -105,6 +105,47 @@ function renderTerminalReport(result, options = {}) {
105
105
  return lines.join("\n");
106
106
  }
107
107
 
108
+ function renderOptimizerFitTerminal(result, options = {}) {
109
+ const useColor = options.color !== false;
110
+ const fit = result.optimizerFit;
111
+ const tone = fit.summary.includes("High") ? "red" : fit.summary.includes("Medium") ? "yellow" : "green";
112
+ const lines = [];
113
+ lines.push("");
114
+ lines.push(color("Prismo Optimizer Fit", "bold", useColor));
115
+ lines.push("");
116
+ lines.push(`Primary bottleneck: ${color(fit.summary, tone, useColor)}`);
117
+ if (result.realUsage && result.realUsage.sessions.length) {
118
+ lines.push(`Local usage: ${formatTokenCount(result.realUsage.totals.displayTokens)} tokens across ${result.realUsage.sessions.length} session(s)`);
119
+ } else if (result.realUsage) {
120
+ lines.push("Local usage: no matching local Claude/Codex sessions found");
121
+ }
122
+ lines.push("");
123
+ lines.push(color("Bottlenecks", "bold", useColor));
124
+ fit.bottlenecks.forEach((item) => {
125
+ lines.push(`- ${item.label}: ${item.level}`);
126
+ item.evidence.slice(0, 2).forEach((evidence) => lines.push(` ${evidence}`));
127
+ });
128
+ lines.push("");
129
+ lines.push(color("Recommended Stack", "bold", useColor));
130
+ fit.recommendedStack.forEach((item) => {
131
+ lines.push(`${item.rank}. ${item.action}`);
132
+ lines.push(` Run: ${item.command}`);
133
+ lines.push(` Why: ${item.why}`);
134
+ lines.push(` Category: ${item.category} (${item.examples.join(", ")})`);
135
+ });
136
+ lines.push("");
137
+ lines.push(color("Tool Fit", "bold", useColor));
138
+ fit.toolFit.forEach((item) => {
139
+ lines.push(`- ${item.category}: ${item.fit}`);
140
+ lines.push(` Examples: ${item.examples.join(", ")}`);
141
+ lines.push(` ${item.reason}`);
142
+ });
143
+ lines.push("");
144
+ lines.push("Notes:");
145
+ fit.caveats.forEach((caveat) => lines.push(`- ${caveat}`));
146
+ return lines.join("\n");
147
+ }
148
+
108
149
  function evaluateCi(result, options = {}) {
109
150
  const minScore = Number(options.minScore || 80);
110
151
  const failures = [];
@@ -392,6 +433,7 @@ function writeReport(result) {
392
433
  evaluateCi,
393
434
  renderCiReport,
394
435
  renderMarkdownReport,
436
+ renderOptimizerFitTerminal,
395
437
  renderSimpleScanReport,
396
438
  renderTerminalReport,
397
439
  writeReport,
@@ -786,6 +786,235 @@ function buildRecommendations({ hasClaudeIgnore, gitignorePatterns, exposedHighR
786
786
  return Array.from(new Set(recs));
787
787
  }
788
788
 
789
+ function levelFromScore(score) {
790
+ if (score >= 70) return "High";
791
+ if (score >= 35) return "Medium";
792
+ return "Low";
793
+ }
794
+
795
+ function addEvidence(evidence, text) {
796
+ if (text && !evidence.includes(text)) evidence.push(text);
797
+ }
798
+
799
+ function countRepeatedSourceReads(realUsage) {
800
+ if (!realUsage || !Array.isArray(realUsage.sessions)) return 0;
801
+ const generatedPattern = /(^|\/)(node_modules|dist|build|coverage|\.next|__pycache__|logs|test-results|playwright-report)\//;
802
+ return realUsage.sessions.reduce((sum, session) => {
803
+ return sum + (session.repeatedPathMentions || []).filter((item) => {
804
+ const value = String(item.value || "");
805
+ if (!value || generatedPattern.test(value)) return false;
806
+ return /\.(js|jsx|ts|tsx|py|go|rs|java|kt|swift|rb|php|cs|svelte|vue|astro|md|json|toml|yaml|yml)$/i.test(value);
807
+ }).reduce((inner, item) => inner + Number(item.count || 0), 0);
808
+ }, 0);
809
+ }
810
+
811
+ function buildOptimizerFit(result) {
812
+ const bottlenecks = [];
813
+ const realUsage = result.realUsage;
814
+ const toolTokens = realUsage ? Number(realUsage.totals.toolTokens || 0) : 0;
815
+ const displayTokens = realUsage ? Number(realUsage.totals.displayTokens || 0) : 0;
816
+ const highRiskSessions = realUsage ? realUsage.sessions.filter((session) => session.contextRisk === "High").length : 0;
817
+ const repeatedSourceReads = countRepeatedSourceReads(realUsage);
818
+
819
+ const ignoreEvidence = [];
820
+ let ignoreScore = 0;
821
+ if (!result.hasClaudeIgnore) {
822
+ ignoreScore += 35;
823
+ addEvidence(ignoreEvidence, ".claudeignore is missing");
824
+ }
825
+ if (!result.hasCursorIgnore) {
826
+ ignoreScore += 20;
827
+ addEvidence(ignoreEvidence, ".cursorignore is missing");
828
+ }
829
+ if (result.exposedHighRiskDirs.length) {
830
+ ignoreScore += Math.min(35, result.exposedHighRiskDirs.length * 8);
831
+ addEvidence(ignoreEvidence, `${result.exposedHighRiskDirs.length} generated/cache directories are exposed`);
832
+ }
833
+ if ((result.sessionIgnoreSuggestions || []).length) {
834
+ ignoreScore += 25;
835
+ addEvidence(ignoreEvidence, `${result.sessionIgnoreSuggestions.length} ignore rules came from actual session leaks`);
836
+ }
837
+ bottlenecks.push({
838
+ id: "ignore-cleanup",
839
+ label: "Generated artifacts / ignore cleanup",
840
+ score: Math.min(100, ignoreScore),
841
+ level: levelFromScore(ignoreScore),
842
+ evidence: ignoreEvidence.length ? ignoreEvidence : ["No major ignore-file leak detected"],
843
+ });
844
+
845
+ const outputEvidence = [];
846
+ let outputScore = result.toolOutputRisk.level === "High" ? 70 : result.toolOutputRisk.level === "Medium" ? 45 : 10;
847
+ if (toolTokens >= 150000) outputScore += 25;
848
+ else if (toolTokens >= 50000) outputScore += 15;
849
+ if (result.toolOutputRisk.exposedNoisyFiles.length) addEvidence(outputEvidence, `${result.toolOutputRisk.exposedNoisyFiles.length} noisy files are exposed`);
850
+ if (result.toolOutputRisk.exposedNoisyDirectories.length) addEvidence(outputEvidence, `${result.toolOutputRisk.exposedNoisyDirectories.length} noisy directories are exposed`);
851
+ if (toolTokens) addEvidence(outputEvidence, `${formatTokenCount(toolTokens)} tool/output tokens found in local sessions`);
852
+ bottlenecks.push({
853
+ id: "output-sandboxing",
854
+ label: "Oversized command/tool output",
855
+ score: Math.min(100, outputScore),
856
+ level: levelFromScore(outputScore),
857
+ evidence: outputEvidence.length ? outputEvidence : ["No dominant command-output flood detected"],
858
+ });
859
+
860
+ const indexEvidence = [];
861
+ let indexScore = 0;
862
+ if (result.stats.sourceFiles >= 1000) indexScore += 35;
863
+ else if (result.stats.sourceFiles >= 250) indexScore += 20;
864
+ if (result.stats.totalFiles >= 5000) indexScore += 25;
865
+ else if (result.stats.totalFiles >= 1000) indexScore += 15;
866
+ if (repeatedSourceReads >= 50) indexScore += 35;
867
+ else if (repeatedSourceReads >= 12) indexScore += 20;
868
+ if (result.stats.sourceFiles >= 250) addEvidence(indexEvidence, `${result.stats.sourceFiles.toLocaleString()} source files`);
869
+ if (repeatedSourceReads) addEvidence(indexEvidence, `${repeatedSourceReads} repeated source-file mentions in local sessions`);
870
+ bottlenecks.push({
871
+ id: "code-indexing",
872
+ label: "Repeated source exploration",
873
+ score: Math.min(100, indexScore),
874
+ level: levelFromScore(indexScore),
875
+ evidence: indexEvidence.length ? indexEvidence : ["Repo/source exploration does not look like the main bottleneck"],
876
+ });
877
+
878
+ const instructionEvidence = [];
879
+ const instructionTokens = result.instructionFiles.reduce((sum, file) => sum + Math.max(0, (file.tokens || 0) - 500), 0);
880
+ let instructionScore = instructionTokens >= 3000 ? 80 : instructionTokens >= 1000 ? 55 : instructionTokens > 0 ? 30 : 0;
881
+ result.instructionFiles
882
+ .filter((file) => file.tokens > 500)
883
+ .slice(0, 3)
884
+ .forEach((file) => addEvidence(instructionEvidence, `${file.path} is ~${(file.tokens || 0).toLocaleString()} tokens`));
885
+ bottlenecks.push({
886
+ id: "instruction-trim",
887
+ label: "Persistent instruction bloat",
888
+ score: Math.min(100, instructionScore),
889
+ level: levelFromScore(instructionScore),
890
+ evidence: instructionEvidence.length ? instructionEvidence : ["Persistent instruction files look manageable"],
891
+ });
892
+
893
+ const sessionEvidence = [];
894
+ let sessionScore = 0;
895
+ if (displayTokens >= 2000000) sessionScore += 60;
896
+ else if (displayTokens >= 500000) sessionScore += 35;
897
+ if (highRiskSessions) sessionScore += Math.min(35, highRiskSessions * 18);
898
+ if (displayTokens) addEvidence(sessionEvidence, `${formatTokenCount(displayTokens)} tokens across recent local sessions`);
899
+ if (highRiskSessions) addEvidence(sessionEvidence, `${highRiskSessions} high-context-risk session${highRiskSessions === 1 ? "" : "s"}`);
900
+ bottlenecks.push({
901
+ id: "session-splitting",
902
+ label: "Long-session context buildup",
903
+ score: Math.min(100, sessionScore),
904
+ level: levelFromScore(sessionScore),
905
+ evidence: sessionEvidence.length ? sessionEvidence : ["No matching high-growth local sessions found"],
906
+ });
907
+
908
+ const mcpEvidence = [];
909
+ let mcpScore = result.optimizationStack.mcpServerTotal >= 10 ? 70 : result.optimizationStack.mcpServerTotal >= 5 ? 45 : 10;
910
+ if (result.optimizationStack.mcpServerTotal) addEvidence(mcpEvidence, `${result.optimizationStack.mcpServerTotal} MCP/tool servers detected`);
911
+ bottlenecks.push({
912
+ id: "tool-surface",
913
+ label: "Tool/MCP surface overhead",
914
+ score: Math.min(100, mcpScore),
915
+ level: levelFromScore(mcpScore),
916
+ evidence: mcpEvidence.length ? mcpEvidence : ["Tool surface does not look unusually large"],
917
+ });
918
+
919
+ const ranked = bottlenecks.sort((a, b) => b.score - a.score || a.label.localeCompare(b.label));
920
+ const primary = ranked[0];
921
+ const actionById = {
922
+ "ignore-cleanup": {
923
+ action: "Apply safe ignore/context fixes first.",
924
+ command: `${NPX_COMMAND} doctor --apply-suggestions --dry-run`,
925
+ category: "ignore cleanup",
926
+ examples: ["Prismo doctor", ".claudeignore", ".cursorignore"],
927
+ },
928
+ "output-sandboxing": {
929
+ action: "Sandbox noisy command output before adding more code-indexing tools.",
930
+ command: `${NPX_COMMAND} shield -- <noisy command>`,
931
+ category: "output sandboxing",
932
+ examples: ["Prismo shield", "context-mode", "RTK", "tokf", "distill"],
933
+ },
934
+ "code-indexing": {
935
+ action: "Use a code indexer if repeated source exploration keeps happening.",
936
+ command: `${NPX_COMMAND} context`,
937
+ category: "code indexing",
938
+ examples: ["codegraph", "jcodemunch", "codebase-memory-mcp", "sigmap"],
939
+ },
940
+ "instruction-trim": {
941
+ action: "Trim persistent instructions before adding runtime compression.",
942
+ command: `${NPX_COMMAND} doctor`,
943
+ category: "instruction quality",
944
+ examples: ["CLAUDE.md cleanup", "AGENTS.md cleanup", "caveman-style concise responses"],
945
+ },
946
+ "session-splitting": {
947
+ action: "Split long sessions and recover from context pressure while working.",
948
+ command: `${NPX_COMMAND} watch --auto`,
949
+ category: "session control",
950
+ examples: ["Prismo watch", "Prismo rescue", "fresh task sessions"],
951
+ },
952
+ "tool-surface": {
953
+ action: "Reduce unused MCP/tool surface for the current task.",
954
+ command: `${NPX_COMMAND} mcp doctor`,
955
+ category: "tool hygiene",
956
+ examples: ["disable unused MCP servers", "strict task-scoped tool config"],
957
+ },
958
+ };
959
+
960
+ const recommendedStack = ranked
961
+ .filter((item) => item.level !== "Low")
962
+ .slice(0, 4)
963
+ .map((item, index) => ({ rank: index + 1, bottleneck: item.id, ...actionById[item.id], why: item.evidence[0] }));
964
+
965
+ if (!recommendedStack.length) {
966
+ recommendedStack.push({
967
+ rank: 1,
968
+ bottleneck: "baseline",
969
+ action: "Keep the stack simple; no major optimizer fit signal was detected.",
970
+ command: `${NPX_COMMAND} watch --once`,
971
+ category: "baseline monitoring",
972
+ examples: ["Prismo watch", "Prismo cc timeline"],
973
+ why: "Repo scan did not find a dominant token-waste source.",
974
+ });
975
+ }
976
+
977
+ return {
978
+ schemaVersion: 1,
979
+ primaryBottleneck: primary.id,
980
+ summary: `${primary.label}: ${primary.level}`,
981
+ bottlenecks: ranked,
982
+ recommendedStack,
983
+ toolFit: [
984
+ {
985
+ category: "PrismoDev workflow",
986
+ fit: "High",
987
+ examples: ["doctor", "watch", "shield", "cc timeline"],
988
+ reason: "Use this first to diagnose repo/session waste and verify before stacking optimizers.",
989
+ },
990
+ {
991
+ category: "Output compression/sandboxing",
992
+ fit: ranked.find((item) => item.id === "output-sandboxing").level,
993
+ examples: ["Prismo shield", "context-mode", "RTK", "tokf", "distill", "headroom"],
994
+ reason: "Best when shell/test/log output is the dominant waste source.",
995
+ },
996
+ {
997
+ category: "Code indexing / AST graph",
998
+ fit: ranked.find((item) => item.id === "code-indexing").level,
999
+ examples: ["codegraph", "jcodemunch", "codebase-memory-mcp", "sigmap"],
1000
+ reason: "Best when the agent repeatedly greps/reads source files to orient itself.",
1001
+ },
1002
+ {
1003
+ category: "Repo packing",
1004
+ fit: result.stats.sourceFiles && result.stats.sourceFiles <= 250 && result.toolOutputRisk.level === "Low" ? "Medium" : "Low",
1005
+ examples: ["repomix", "Prismo context packs"],
1006
+ reason: "Best for one-shot repo handoff, less ideal for long live coding sessions.",
1007
+ },
1008
+ ],
1009
+ caveats: [
1010
+ "Do not stack optimizers blindly; measure one real workflow before and after.",
1011
+ "Payload reduction is not the same as workflow savings; repeated tool calls can erase compression wins.",
1012
+ "Token savings are only useful if the agent still finds the right files and produces accepted changes.",
1013
+ ],
1014
+ nextCommands: recommendedStack.map((item) => item.command),
1015
+ };
1016
+ }
1017
+
789
1018
  function scoreScan(issues, stats, context = {}) {
790
1019
  const issuePenalty = issues.reduce((sum, issue) => sum + severityWeight(issue.severity), 0);
791
1020
  const repoPenalty =
@@ -897,6 +1126,7 @@ function toJsonPayload(result) {
897
1126
  optimizationStack: result.optimizationStack,
898
1127
  toolOutputRisk: result.toolOutputRisk,
899
1128
  operationalNoise: result.operationalNoise,
1129
+ optimizerFit: result.optimizerFit,
900
1130
  sessionIgnoreSuggestions: result.sessionIgnoreSuggestions || [],
901
1131
  proxyTrackingReadiness: result.proxyTrackingReadiness,
902
1132
  suggestedClaudeIgnore: result.recommendedClaudeIgnore,
@@ -1308,7 +1538,7 @@ function scanRepo(rootDir = process.cwd(), options = {}) {
1308
1538
  });
1309
1539
  buildRealUsageRecommendations(realUsage).forEach((rec) => recommendations.push(rec));
1310
1540
 
1311
- return {
1541
+ const scanResult = {
1312
1542
  root,
1313
1543
  score: score.score,
1314
1544
  risk: score.risk,
@@ -1344,6 +1574,8 @@ function scanRepo(rootDir = process.cwd(), options = {}) {
1344
1574
  topTokenLeaks: getTopTokenLeaks(issues),
1345
1575
  generatedAt: new Date().toISOString(),
1346
1576
  };
1577
+ scanResult.optimizerFit = buildOptimizerFit(scanResult);
1578
+ return scanResult;
1347
1579
  }
1348
1580
 
1349
1581
  return {
@@ -193,6 +193,7 @@ const {
193
193
  evaluateCi,
194
194
  renderCiReport,
195
195
  renderMarkdownReport,
196
+ renderOptimizerFitTerminal,
196
197
  renderSimpleScanReport,
197
198
  renderTerminalReport,
198
199
  writeReport,
@@ -305,7 +306,7 @@ Usage:
305
306
  prismo mcp [path]
306
307
  prismo mcp doctor [--json] [path]
307
308
  prismo setup [--json] [--proxy-url URL] [path]
308
- prismo scan [--fix] [--ci] [--json] [--usage] [--simple] [--no-report] [path]
309
+ prismo scan [--fix] [--ci] [--json] [--usage] [--optimizer-fit] [--simple] [--no-report] [path]
309
310
  prismo optimize [scope] [--json] [path]
310
311
  prismo context [scope] [--json] [path]
311
312
  prismo cc [list|last N|all] [--json] [--limit N] [path]
@@ -334,6 +335,7 @@ Options:
334
335
  --ci Fail with exit code 1 when token-risk gates fail.
335
336
  --json Output valid JSON only for CI or future dashboard ingestion.
336
337
  --usage Include real local Codex/Claude Code session usage in scan diagnostics.
338
+ --optimizer-fit Recommend the right optimization path for this repo/session.
337
339
  --simple Print a plain-English scan summary for first-time or non-technical users.
338
340
  --no-report Do not write .prismo/prismo-dev-report.md.
339
341
  --limit N Number of recent local sessions to show.
@@ -373,18 +375,21 @@ function printCommandHelp(command) {
373
375
  scan: `PrismoDev
374
376
 
375
377
  Usage:
376
- prismo scan [--fix] [--ci] [--json] [--usage] [--simple] [--no-report] [--limit N] [path]
378
+ prismo scan [--fix] [--ci] [--json] [--usage] [--optimizer-fit] [--simple] [--no-report] [--limit N] [path]
377
379
 
378
380
  Examples:
379
381
  prismo scan
380
382
  prismo scan --usage
383
+ prismo scan --optimizer-fit
381
384
  prismo scan --simple
382
385
  prismo scan --fix
383
386
  prismo scan --ci
384
387
  prismo scan --usage --json --no-report
388
+ prismo scan --optimizer-fit --json
385
389
 
386
390
  Notes:
387
391
  --usage reads local Codex/Claude Code logs when present.
392
+ --optimizer-fit explains whether ignore cleanup, output sandboxing, code indexing, repo packing, instruction trimming, or session splitting fits this repo best.
388
393
  --simple keeps the output short and does not write a report unless combined with --fix.
389
394
  --fix creates safe recommendation files and never overwrites CLAUDE.md or AGENTS.md.`,
390
395
  optimize: `Prismo Optimize
@@ -920,12 +925,13 @@ async function runCli(argv) {
920
925
  const noReport = rest.includes("--no-report");
921
926
  const json = rest.includes("--json");
922
927
  const simple = rest.includes("--simple");
928
+ const optimizerFit = rest.includes("--optimizer-fit");
923
929
  const ciMode = rest.includes("--ci");
924
- const includeUsage = rest.includes("--usage");
930
+ const includeUsage = rest.includes("--usage") || optimizerFit;
925
931
  const limitIndex = rest.indexOf("--limit");
926
932
  const usageToolIndex = rest.indexOf("--usage-tool");
927
933
  const target = getPositionals(rest, new Set(["--limit", "--usage-tool"]))[0] || process.cwd();
928
- const scanDone = printStep(includeUsage ? "Scanning repo and local usage" : "Scanning repo", json || simple);
934
+ const scanDone = printStep(includeUsage ? "Scanning repo and local usage" : "Scanning repo", json || simple || optimizerFit);
929
935
  const result = scanRepo(target, {
930
936
  includeUsage,
931
937
  usageLimit: parsePositiveInt(limitIndex >= 0 ? rest[limitIndex + 1] : null, 5),
@@ -938,7 +944,7 @@ async function runCli(argv) {
938
944
  let report = null;
939
945
  if (fix) {
940
946
  fixActions = applyFixes(result);
941
- } else if (!noReport) {
947
+ } else if (!noReport && !optimizerFit) {
942
948
  report = writeReport(result);
943
949
  }
944
950
  const payload = toJsonPayload(result);
@@ -946,13 +952,26 @@ async function runCli(argv) {
946
952
  payload.ci = evaluateCi(result);
947
953
  if (!payload.ci.passed) process.exitCode = 1;
948
954
  }
955
+ if (optimizerFit) {
956
+ console.log(JSON.stringify({
957
+ schemaVersion: 1,
958
+ scannedPath: result.root,
959
+ score: result.score,
960
+ riskLevel: result.risk,
961
+ optimizerFit: result.optimizerFit,
962
+ generatedAt: result.generatedAt,
963
+ }, null, 2));
964
+ return;
965
+ }
949
966
  if (fixActions.length) payload.fixActions = fixActions;
950
967
  if (report) payload.reportPath = report.reportPath;
951
968
  console.log(JSON.stringify(payload, null, 2));
952
969
  return;
953
970
  }
954
971
 
955
- if (simple) {
972
+ if (optimizerFit) {
973
+ console.log(renderOptimizerFitTerminal(result));
974
+ } else if (simple) {
956
975
  console.log(renderSimpleScanReport(result));
957
976
  } else if (ciMode) {
958
977
  const ci = evaluateCi(result);
@@ -966,7 +985,7 @@ async function runCli(argv) {
966
985
  const actions = applyFixes(result);
967
986
  console.log("\nFix Mode:");
968
987
  actions.forEach((action) => console.log(`- ${action}`));
969
- } else if (!noReport && !simple) {
988
+ } else if (!noReport && !simple && !optimizerFit) {
970
989
  const report = writeReport(result);
971
990
  if (report.backupPath) {
972
991
  console.log(`\nExisting report backed up to ${path.basename(report.backupPath)}.`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "getprismo",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "Local AI coding workflow scanner for Codex, Claude Code, Cursor, and token-waste diagnostics.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/shanirsh/prismodev#readme",