nairon-bench 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +500 -206
- package/package.json +5 -3
- package/postinstall.js +22 -0
package/dist/index.js
CHANGED
|
@@ -4447,8 +4447,8 @@ function defineCommand2(def) {
|
|
|
4447
4447
|
|
|
4448
4448
|
// src/commands/scan.ts
|
|
4449
4449
|
init_dist();
|
|
4450
|
-
import { existsSync as
|
|
4451
|
-
import { join as
|
|
4450
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5, readFileSync as readFileSync10 } from "node:fs";
|
|
4451
|
+
import { join as join10 } from "node:path";
|
|
4452
4452
|
|
|
4453
4453
|
// ../../node_modules/simple-git/dist/esm/index.js
|
|
4454
4454
|
var import_file_exists = __toESM(require_dist(), 1);
|
|
@@ -16068,6 +16068,211 @@ function filterAlreadyInstalled(optimizations, status) {
|
|
|
16068
16068
|
});
|
|
16069
16069
|
}
|
|
16070
16070
|
|
|
16071
|
+
// src/lib/first-run.ts
|
|
16072
|
+
init_dist();
|
|
16073
|
+
import { existsSync as existsSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4 } from "node:fs";
|
|
16074
|
+
import { homedir as homedir8 } from "node:os";
|
|
16075
|
+
import { join as join9 } from "node:path";
|
|
16076
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
16077
|
+
var FIRST_RUN_FLAG = join9(homedir8(), ".nairon-bench", "first-run-complete");
|
|
16078
|
+
var PROJECT_SCAN_MARKER = ".nairon/first-scan-complete";
|
|
16079
|
+
function isFirstScanInProject(projectDir) {
|
|
16080
|
+
return !existsSync9(join9(projectDir, PROJECT_SCAN_MARKER));
|
|
16081
|
+
}
|
|
16082
|
+
function markProjectScanned(projectDir) {
|
|
16083
|
+
const naironDir = join9(projectDir, ".nairon");
|
|
16084
|
+
if (!existsSync9(naironDir)) {
|
|
16085
|
+
mkdirSync4(naironDir, { recursive: true });
|
|
16086
|
+
}
|
|
16087
|
+
writeFileSync4(join9(projectDir, PROJECT_SCAN_MARKER), new Date().toISOString());
|
|
16088
|
+
}
|
|
16089
|
+
function detectAgent() {
|
|
16090
|
+
const home = homedir8();
|
|
16091
|
+
const claudeConfig = join9(home, ".claude");
|
|
16092
|
+
const hasClaudeCode = existsSync9(claudeConfig);
|
|
16093
|
+
const opencodeConfig = join9(home, ".config", "opencode");
|
|
16094
|
+
const opencodeData = join9(home, ".local", "share", "opencode");
|
|
16095
|
+
const hasOpenCode = existsSync9(opencodeConfig) || existsSync9(opencodeData);
|
|
16096
|
+
const cursorConfig = join9(home, ".cursor");
|
|
16097
|
+
const hasCursor = existsSync9(cursorConfig);
|
|
16098
|
+
if (hasClaudeCode)
|
|
16099
|
+
return "claude-code";
|
|
16100
|
+
if (hasOpenCode)
|
|
16101
|
+
return "opencode";
|
|
16102
|
+
if (hasCursor)
|
|
16103
|
+
return "cursor";
|
|
16104
|
+
return "unknown";
|
|
16105
|
+
}
|
|
16106
|
+
function analyzeReadme(projectDir) {
|
|
16107
|
+
const readmePath = join9(projectDir, "README.md");
|
|
16108
|
+
if (!existsSync9(readmePath)) {
|
|
16109
|
+
const alternatives = ["readme.md", "Readme.md", "README.MD", "README"];
|
|
16110
|
+
for (const alt of alternatives) {
|
|
16111
|
+
const altPath = join9(projectDir, alt);
|
|
16112
|
+
if (existsSync9(altPath)) {
|
|
16113
|
+
return parseReadme(readFileSync9(altPath, "utf-8"), projectDir);
|
|
16114
|
+
}
|
|
16115
|
+
}
|
|
16116
|
+
return null;
|
|
16117
|
+
}
|
|
16118
|
+
const content = readFileSync9(readmePath, "utf-8");
|
|
16119
|
+
return parseReadme(content, projectDir);
|
|
16120
|
+
}
|
|
16121
|
+
function parseReadme(content, projectDir) {
|
|
16122
|
+
let name = "Unknown Project";
|
|
16123
|
+
const pkgPath = join9(projectDir, "package.json");
|
|
16124
|
+
if (existsSync9(pkgPath)) {
|
|
16125
|
+
try {
|
|
16126
|
+
const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
|
|
16127
|
+
if (pkg.name && !pkg.name.startsWith("@") && pkg.name !== "root") {
|
|
16128
|
+
name = pkg.name;
|
|
16129
|
+
}
|
|
16130
|
+
} catch {}
|
|
16131
|
+
}
|
|
16132
|
+
if (name === "Unknown Project") {
|
|
16133
|
+
const headingMatch = content.match(/^#\s+([^<\n]+)$/m);
|
|
16134
|
+
if (headingMatch && headingMatch[1]) {
|
|
16135
|
+
const heading = headingMatch[1].trim();
|
|
16136
|
+
if (!heading.toLowerCase().includes("install") && !heading.toLowerCase().includes("getting started") && heading.length < 50) {
|
|
16137
|
+
name = heading;
|
|
16138
|
+
}
|
|
16139
|
+
}
|
|
16140
|
+
}
|
|
16141
|
+
let description = "";
|
|
16142
|
+
const descMatch = content.match(/^#[^#].*\n\n(.+?)(\n\n|$)/s);
|
|
16143
|
+
if (descMatch && descMatch[1]) {
|
|
16144
|
+
description = descMatch[1].replace(/\n/g, " ").trim().slice(0, 200);
|
|
16145
|
+
}
|
|
16146
|
+
const techStack = [];
|
|
16147
|
+
const techPatterns = {
|
|
16148
|
+
react: /\breact\b/i,
|
|
16149
|
+
"next.js": /\bnext\.?js\b/i,
|
|
16150
|
+
vue: /\bvue\b/i,
|
|
16151
|
+
svelte: /\bsvelte\b/i,
|
|
16152
|
+
typescript: /\btypescript\b/i,
|
|
16153
|
+
python: /\bpython\b/i,
|
|
16154
|
+
rust: /\brust\b/i,
|
|
16155
|
+
go: /\bgolang?\b/i,
|
|
16156
|
+
node: /\bnode\.?js\b/i,
|
|
16157
|
+
bun: /\bbun\b/i,
|
|
16158
|
+
deno: /\bdeno\b/i,
|
|
16159
|
+
tailwind: /\btailwind\b/i,
|
|
16160
|
+
prisma: /\bprisma\b/i,
|
|
16161
|
+
postgres: /\bpostgres\b/i,
|
|
16162
|
+
mongodb: /\bmongo\b/i,
|
|
16163
|
+
redis: /\bredis\b/i,
|
|
16164
|
+
docker: /\bdocker\b/i,
|
|
16165
|
+
kubernetes: /\bkubernetes\b|\bk8s\b/i,
|
|
16166
|
+
aws: /\baws\b/i,
|
|
16167
|
+
vercel: /\bvercel\b/i,
|
|
16168
|
+
cloudflare: /\bcloudflare\b/i,
|
|
16169
|
+
openai: /\bopenai\b/i,
|
|
16170
|
+
anthropic: /\banthropic\b|\bclaude\b/i,
|
|
16171
|
+
langchain: /\blangchain\b/i,
|
|
16172
|
+
convex: /\bconvex\b/i,
|
|
16173
|
+
supabase: /\bsupabase\b/i,
|
|
16174
|
+
firebase: /\bfirebase\b/i,
|
|
16175
|
+
stripe: /\bstripe\b/i,
|
|
16176
|
+
playwright: /\bplaywright\b/i,
|
|
16177
|
+
vitest: /\bvitest\b/i,
|
|
16178
|
+
jest: /\bjest\b/i,
|
|
16179
|
+
remotion: /\bremotion\b/i
|
|
16180
|
+
};
|
|
16181
|
+
for (const [tech, pattern] of Object.entries(techPatterns)) {
|
|
16182
|
+
if (pattern.test(content)) {
|
|
16183
|
+
techStack.push(tech);
|
|
16184
|
+
}
|
|
16185
|
+
}
|
|
16186
|
+
const keywords = [];
|
|
16187
|
+
const keywordPatterns = {
|
|
16188
|
+
api: /\bapi\b|\brest\b|\bgraphql\b/i,
|
|
16189
|
+
cli: /\bcli\b|\bcommand.?line\b/i,
|
|
16190
|
+
web: /\bweb\b|\bwebsite\b|\bfrontend\b/i,
|
|
16191
|
+
mobile: /\bmobile\b|\bios\b|\bandroid\b|\breact.?native\b/i,
|
|
16192
|
+
ai: /\bai\b|\bmachine.?learning\b|\bllm\b|\bgpt\b/i,
|
|
16193
|
+
video: /\bvideo\b|\bstreaming\b|\bmedia\b/i,
|
|
16194
|
+
ecommerce: /\becommerce\b|\bshop\b|\bstore\b|\bpayment\b/i,
|
|
16195
|
+
auth: /\bauth\b|\blogin\b|\bsession\b/i,
|
|
16196
|
+
testing: /\btest\b|\btesting\b|\btdd\b/i,
|
|
16197
|
+
devtools: /\bdevtool\b|\bdeveloper.?tool\b/i
|
|
16198
|
+
};
|
|
16199
|
+
for (const [keyword, pattern] of Object.entries(keywordPatterns)) {
|
|
16200
|
+
if (pattern.test(content)) {
|
|
16201
|
+
keywords.push(keyword);
|
|
16202
|
+
}
|
|
16203
|
+
}
|
|
16204
|
+
return { name, description, techStack, keywords };
|
|
16205
|
+
}
|
|
16206
|
+
function suggestSkills(context) {
|
|
16207
|
+
const suggestions = [];
|
|
16208
|
+
suggestions.push({
|
|
16209
|
+
name: "Find Skills",
|
|
16210
|
+
installCommand: "npx skills add vercel-labs/skills@find-skills --yes",
|
|
16211
|
+
reason: "Discover more skills for your workflow"
|
|
16212
|
+
});
|
|
16213
|
+
if (!context) {
|
|
16214
|
+
suggestions.push({
|
|
16215
|
+
name: "Writing Plans",
|
|
16216
|
+
installCommand: "npx skills add obra/superpowers@writing-plans --yes",
|
|
16217
|
+
reason: "Better planning before implementation"
|
|
16218
|
+
});
|
|
16219
|
+
return suggestions;
|
|
16220
|
+
}
|
|
16221
|
+
if (context.techStack.includes("react") || context.techStack.includes("next.js")) {
|
|
16222
|
+
suggestions.push({
|
|
16223
|
+
name: "React Best Practices",
|
|
16224
|
+
installCommand: "npx skills add vercel-labs/agent-skills@vercel-react-best-practices --yes",
|
|
16225
|
+
reason: `Detected React/Next.js in ${context.name}`
|
|
16226
|
+
});
|
|
16227
|
+
}
|
|
16228
|
+
if (context.techStack.includes("remotion")) {
|
|
16229
|
+
suggestions.push({
|
|
16230
|
+
name: "Remotion",
|
|
16231
|
+
installCommand: "npx skills add remotion-dev/skills@remotion-best-practices --yes",
|
|
16232
|
+
reason: "Detected Remotion video framework"
|
|
16233
|
+
});
|
|
16234
|
+
}
|
|
16235
|
+
if (context.keywords.includes("testing") || context.keywords.includes("tdd")) {
|
|
16236
|
+
suggestions.push({
|
|
16237
|
+
name: "Test-Driven Development",
|
|
16238
|
+
installCommand: "npx skills add obra/superpowers@test-driven-development --yes",
|
|
16239
|
+
reason: "Testing focus detected"
|
|
16240
|
+
});
|
|
16241
|
+
}
|
|
16242
|
+
if (context.keywords.includes("web")) {
|
|
16243
|
+
suggestions.push({
|
|
16244
|
+
name: "Web Design Guidelines",
|
|
16245
|
+
installCommand: "npx skills add vercel-labs/agent-skills@web-design-guidelines --yes",
|
|
16246
|
+
reason: "Web project detected"
|
|
16247
|
+
});
|
|
16248
|
+
}
|
|
16249
|
+
if (!suggestions.some((s2) => s2.name.includes("Plan"))) {
|
|
16250
|
+
suggestions.push({
|
|
16251
|
+
name: "Writing Plans",
|
|
16252
|
+
installCommand: "npx skills add obra/superpowers@writing-plans --yes",
|
|
16253
|
+
reason: "Helps structure work before coding"
|
|
16254
|
+
});
|
|
16255
|
+
}
|
|
16256
|
+
return suggestions.slice(0, 5);
|
|
16257
|
+
}
|
|
16258
|
+
function installSkill2(installCommand) {
|
|
16259
|
+
try {
|
|
16260
|
+
const result = spawnSync2("npx", installCommand.replace("npx ", "").split(" "), {
|
|
16261
|
+
stdio: "pipe",
|
|
16262
|
+
timeout: 60000,
|
|
16263
|
+
shell: true
|
|
16264
|
+
});
|
|
16265
|
+
if (result.status === 0) {
|
|
16266
|
+
return { success: true, message: "Installed successfully" };
|
|
16267
|
+
} else {
|
|
16268
|
+
const stderr = result.stderr?.toString() || "";
|
|
16269
|
+
return { success: false, message: stderr.slice(0, 100) || "Installation failed" };
|
|
16270
|
+
}
|
|
16271
|
+
} catch (error2) {
|
|
16272
|
+
return { success: false, message: error2 instanceof Error ? error2.message : "Unknown error" };
|
|
16273
|
+
}
|
|
16274
|
+
}
|
|
16275
|
+
|
|
16071
16276
|
// src/commands/scan.ts
|
|
16072
16277
|
var scanCommand = defineCommand2({
|
|
16073
16278
|
meta: {
|
|
@@ -16109,6 +16314,10 @@ var scanCommand = defineCommand2({
|
|
|
16109
16314
|
]
|
|
16110
16315
|
});
|
|
16111
16316
|
since = parseSince(period);
|
|
16317
|
+
if (isFirstScanInProject(projectDir)) {
|
|
16318
|
+
await showFirstScanWelcome(projectDir);
|
|
16319
|
+
markProjectScanned(projectDir);
|
|
16320
|
+
}
|
|
16112
16321
|
}
|
|
16113
16322
|
const useCache = true;
|
|
16114
16323
|
const watchMode = false;
|
|
@@ -16245,7 +16454,7 @@ var scanCommand = defineCommand2({
|
|
|
16245
16454
|
console.log(` Projected monthly: ${colors2.primary(`$${scanCost.projectedMonthlyCostUsd.toFixed(2)}`)}`);
|
|
16246
16455
|
console.log(colors2.dim(" " + "═".repeat(45)));
|
|
16247
16456
|
console.log();
|
|
16248
|
-
const reportDir =
|
|
16457
|
+
const reportDir = join10(projectDir, ".nairon/reports");
|
|
16249
16458
|
const reportPath = generateReport(reportDir, score, git, agents, tests, "7d", sdlcAnalysis, scanCost, analysis);
|
|
16250
16459
|
console.log(` ${icons.success} Report saved: ${colors2.dim(reportPath)}`);
|
|
16251
16460
|
if (agents && agents.sessions.length > 0) {
|
|
@@ -16461,12 +16670,12 @@ var scanCommand = defineCommand2({
|
|
|
16461
16670
|
}
|
|
16462
16671
|
});
|
|
16463
16672
|
function loadProjectContext(projectDir) {
|
|
16464
|
-
const contextPath =
|
|
16465
|
-
if (!
|
|
16673
|
+
const contextPath = join10(projectDir, ".nairon", "context.json");
|
|
16674
|
+
if (!existsSync10(contextPath)) {
|
|
16466
16675
|
return null;
|
|
16467
16676
|
}
|
|
16468
16677
|
try {
|
|
16469
|
-
const raw =
|
|
16678
|
+
const raw = readFileSync10(contextPath, "utf-8");
|
|
16470
16679
|
const data = JSON.parse(raw);
|
|
16471
16680
|
const context = {
|
|
16472
16681
|
painPoints: data.painPoints || [],
|
|
@@ -16519,12 +16728,12 @@ function parseSince(since) {
|
|
|
16519
16728
|
return new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
|
|
16520
16729
|
}
|
|
16521
16730
|
function generateReport(reportDir, score, git, agents, tests, since, sdlcAnalysis, scanCost, analysis) {
|
|
16522
|
-
if (!
|
|
16523
|
-
|
|
16731
|
+
if (!existsSync10(reportDir)) {
|
|
16732
|
+
mkdirSync5(reportDir, { recursive: true });
|
|
16524
16733
|
}
|
|
16525
16734
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
16526
16735
|
const filename = `scan-${timestamp}.md`;
|
|
16527
|
-
const filepath =
|
|
16736
|
+
const filepath = join10(reportDir, filename);
|
|
16528
16737
|
const lines = [];
|
|
16529
16738
|
lines.push(`# NaironAI Scan Report`);
|
|
16530
16739
|
lines.push("");
|
|
@@ -16640,7 +16849,7 @@ function generateReport(reportDir, score, git, agents, tests, since, sdlcAnalysi
|
|
|
16640
16849
|
lines.push("---");
|
|
16641
16850
|
lines.push("");
|
|
16642
16851
|
lines.push("*Generated by [nairon-bench](https://github.com/ObaidUr-Rahmaan/nairon-bench)*");
|
|
16643
|
-
|
|
16852
|
+
writeFileSync5(filepath, lines.join(`
|
|
16644
16853
|
`));
|
|
16645
16854
|
return filepath;
|
|
16646
16855
|
}
|
|
@@ -16659,15 +16868,73 @@ function formatTokensPlain(tokens) {
|
|
|
16659
16868
|
return `${Math.round(tokens / 1000)}K`;
|
|
16660
16869
|
return tokens.toString();
|
|
16661
16870
|
}
|
|
16871
|
+
async function showFirstScanWelcome(projectDir) {
|
|
16872
|
+
console.log();
|
|
16873
|
+
console.log(colors2.dim(" " + "═".repeat(50)));
|
|
16874
|
+
console.log(` ${colors2.primary("✨")} ${colors2.bold("First scan in this project!")}`);
|
|
16875
|
+
console.log(colors2.dim(" " + "═".repeat(50)));
|
|
16876
|
+
console.log();
|
|
16877
|
+
const agent = detectAgent();
|
|
16878
|
+
const agentNames = {
|
|
16879
|
+
"claude-code": "Claude Code",
|
|
16880
|
+
opencode: "OpenCode",
|
|
16881
|
+
cursor: "Cursor",
|
|
16882
|
+
unknown: "Unknown"
|
|
16883
|
+
};
|
|
16884
|
+
console.log(` ${icons.info} Detected agent: ${colors2.bold(agentNames[agent])}`);
|
|
16885
|
+
const context = analyzeReadme(projectDir);
|
|
16886
|
+
if (context) {
|
|
16887
|
+
console.log(` ${icons.info} Project: ${colors2.bold(context.name)}`);
|
|
16888
|
+
if (context.techStack.length > 0) {
|
|
16889
|
+
console.log(` ${colors2.dim(" Tech: " + context.techStack.slice(0, 4).join(", "))}`);
|
|
16890
|
+
}
|
|
16891
|
+
}
|
|
16892
|
+
console.log();
|
|
16893
|
+
const suggestions = suggestSkills(context);
|
|
16894
|
+
if (suggestions.length > 0) {
|
|
16895
|
+
console.log(` ${colors2.bold("Recommended skills for this project:")}`);
|
|
16896
|
+
console.log();
|
|
16897
|
+
for (let i3 = 0;i3 < Math.min(3, suggestions.length); i3++) {
|
|
16898
|
+
const s2 = suggestions[i3];
|
|
16899
|
+
console.log(` ${colors2.primary((i3 + 1).toString())}. ${colors2.bold(s2.name)}`);
|
|
16900
|
+
console.log(` ${colors2.dim(s2.reason)}`);
|
|
16901
|
+
}
|
|
16902
|
+
console.log();
|
|
16903
|
+
const installChoice = await consola.prompt("Install recommended skills?", {
|
|
16904
|
+
type: "select",
|
|
16905
|
+
options: [
|
|
16906
|
+
{ value: "find-skills", label: "Just find-skills (discover more skills later)" },
|
|
16907
|
+
{ value: "all", label: "All recommended skills" },
|
|
16908
|
+
{ value: "skip", label: "Skip - continue to scan" }
|
|
16909
|
+
]
|
|
16910
|
+
});
|
|
16911
|
+
if (installChoice === "find-skills" || installChoice === "all") {
|
|
16912
|
+
console.log();
|
|
16913
|
+
const toInstall = installChoice === "all" ? suggestions.slice(0, 3) : suggestions.slice(0, 1);
|
|
16914
|
+
for (const skill of toInstall) {
|
|
16915
|
+
process.stdout.write(` Installing ${skill.name}...`);
|
|
16916
|
+
const result = installSkill2(skill.installCommand);
|
|
16917
|
+
if (result.success) {
|
|
16918
|
+
console.log(` ${colors2.success("✓")}`);
|
|
16919
|
+
} else {
|
|
16920
|
+
console.log(` ${colors2.warning("⚠")} ${colors2.dim(`(${result.message.slice(0, 50)})`)}`);
|
|
16921
|
+
}
|
|
16922
|
+
}
|
|
16923
|
+
console.log();
|
|
16924
|
+
}
|
|
16925
|
+
}
|
|
16926
|
+
console.log(colors2.dim(" " + "═".repeat(50)));
|
|
16927
|
+
console.log();
|
|
16928
|
+
}
|
|
16662
16929
|
|
|
16663
16930
|
// src/commands/report.ts
|
|
16664
16931
|
init_dist();
|
|
16665
16932
|
init_client();
|
|
16666
16933
|
|
|
16667
16934
|
// src/collectors/report-data.ts
|
|
16668
|
-
import { existsSync as
|
|
16669
|
-
import { homedir as
|
|
16670
|
-
import { join as
|
|
16935
|
+
import { existsSync as existsSync11, readdirSync as readdirSync5, readFileSync as readFileSync11, statSync as statSync2 } from "node:fs";
|
|
16936
|
+
import { homedir as homedir9 } from "node:os";
|
|
16937
|
+
import { join as join11, basename as basename3 } from "node:path";
|
|
16671
16938
|
async function collectReportData(projectDir, since, until = new Date, harness) {
|
|
16672
16939
|
const projectName = basename3(projectDir);
|
|
16673
16940
|
const [commits, allSessions, mcpConfigs] = await Promise.all([
|
|
@@ -16750,12 +17017,12 @@ function detectAIAssistedCommit(message) {
|
|
|
16750
17017
|
}
|
|
16751
17018
|
async function collectAllSessions(since, until, projectDir) {
|
|
16752
17019
|
const sessions = [];
|
|
16753
|
-
const claudeDir =
|
|
16754
|
-
if (
|
|
17020
|
+
const claudeDir = join11(homedir9(), ".claude");
|
|
17021
|
+
if (existsSync11(claudeDir)) {
|
|
16755
17022
|
sessions.push(...collectClaudeCodeSessions(claudeDir, since, until, projectDir));
|
|
16756
17023
|
}
|
|
16757
|
-
const openCodeDir =
|
|
16758
|
-
if (
|
|
17024
|
+
const openCodeDir = join11(homedir9(), ".local", "share", "opencode");
|
|
17025
|
+
if (existsSync11(openCodeDir)) {
|
|
16759
17026
|
sessions.push(...collectOpenCodeSessions2(openCodeDir, since, until));
|
|
16760
17027
|
}
|
|
16761
17028
|
sessions.sort((a2, b2) => a2.startTime.getTime() - b2.startTime.getTime());
|
|
@@ -16763,15 +17030,15 @@ async function collectAllSessions(since, until, projectDir) {
|
|
|
16763
17030
|
}
|
|
16764
17031
|
function collectClaudeCodeSessions(claudeDir, since, until, projectDir) {
|
|
16765
17032
|
const sessions = [];
|
|
16766
|
-
const transcriptsDir =
|
|
16767
|
-
if (!
|
|
17033
|
+
const transcriptsDir = join11(claudeDir, "transcripts");
|
|
17034
|
+
if (!existsSync11(transcriptsDir))
|
|
16768
17035
|
return sessions;
|
|
16769
17036
|
const projectHash = projectDir ? hashPath(projectDir) : null;
|
|
16770
|
-
const projectsDir =
|
|
17037
|
+
const projectsDir = join11(claudeDir, "projects");
|
|
16771
17038
|
try {
|
|
16772
17039
|
const transcriptFiles = readdirSync5(transcriptsDir).filter((f3) => f3.endsWith(".jsonl"));
|
|
16773
17040
|
for (const file of transcriptFiles) {
|
|
16774
|
-
const filePath =
|
|
17041
|
+
const filePath = join11(transcriptsDir, file);
|
|
16775
17042
|
const stat = statSync2(filePath);
|
|
16776
17043
|
if (stat.mtime < since || stat.mtime > until)
|
|
16777
17044
|
continue;
|
|
@@ -16782,12 +17049,12 @@ function collectClaudeCodeSessions(claudeDir, since, until, projectDir) {
|
|
|
16782
17049
|
}
|
|
16783
17050
|
} catch {}
|
|
16784
17051
|
}
|
|
16785
|
-
if (projectHash &&
|
|
16786
|
-
const projectSessionDir =
|
|
16787
|
-
if (
|
|
17052
|
+
if (projectHash && existsSync11(projectsDir)) {
|
|
17053
|
+
const projectSessionDir = join11(projectsDir, projectHash);
|
|
17054
|
+
if (existsSync11(projectSessionDir)) {
|
|
16788
17055
|
const projectFiles = readdirSync5(projectSessionDir).filter((f3) => f3.endsWith(".jsonl"));
|
|
16789
17056
|
for (const file of projectFiles) {
|
|
16790
|
-
const filePath =
|
|
17057
|
+
const filePath = join11(projectSessionDir, file);
|
|
16791
17058
|
const stat = statSync2(filePath);
|
|
16792
17059
|
if (stat.mtime < since || stat.mtime > until)
|
|
16793
17060
|
continue;
|
|
@@ -16806,7 +17073,7 @@ function collectClaudeCodeSessions(claudeDir, since, until, projectDir) {
|
|
|
16806
17073
|
return sessions;
|
|
16807
17074
|
}
|
|
16808
17075
|
function parseClaudeTranscript(filePath, fileName) {
|
|
16809
|
-
const content =
|
|
17076
|
+
const content = readFileSync11(filePath, "utf-8");
|
|
16810
17077
|
const lines = content.trim().split(`
|
|
16811
17078
|
`).filter((l2) => l2.trim());
|
|
16812
17079
|
if (lines.length === 0)
|
|
@@ -16896,25 +17163,25 @@ function parseClaudeTranscript(filePath, fileName) {
|
|
|
16896
17163
|
}
|
|
16897
17164
|
function collectOpenCodeSessions2(openCodeDir, since, until) {
|
|
16898
17165
|
const sessions = [];
|
|
16899
|
-
const sessionDir =
|
|
16900
|
-
const messageDir =
|
|
16901
|
-
const partDir =
|
|
16902
|
-
if (!
|
|
17166
|
+
const sessionDir = join11(openCodeDir, "storage", "session");
|
|
17167
|
+
const messageDir = join11(openCodeDir, "storage", "message");
|
|
17168
|
+
const partDir = join11(openCodeDir, "storage", "part");
|
|
17169
|
+
if (!existsSync11(sessionDir))
|
|
16903
17170
|
return sessions;
|
|
16904
17171
|
try {
|
|
16905
|
-
const projectDirs = readdirSync5(sessionDir, { withFileTypes: true }).filter((d2) => d2.isDirectory()).map((d2) =>
|
|
17172
|
+
const projectDirs = readdirSync5(sessionDir, { withFileTypes: true }).filter((d2) => d2.isDirectory()).map((d2) => join11(sessionDir, d2.name));
|
|
16906
17173
|
for (const projectDir of projectDirs) {
|
|
16907
17174
|
const sessionFiles = readdirSync5(projectDir).filter((f3) => f3.endsWith(".json"));
|
|
16908
17175
|
for (const sessionFile of sessionFiles) {
|
|
16909
17176
|
try {
|
|
16910
|
-
const sessionPath =
|
|
16911
|
-
const sessionData = JSON.parse(
|
|
17177
|
+
const sessionPath = join11(projectDir, sessionFile);
|
|
17178
|
+
const sessionData = JSON.parse(readFileSync11(sessionPath, "utf-8"));
|
|
16912
17179
|
const createdAt = new Date(sessionData.time?.created || 0);
|
|
16913
17180
|
const updatedAt = new Date(sessionData.time?.updated || sessionData.time?.created || 0);
|
|
16914
17181
|
if (updatedAt < since || createdAt > until)
|
|
16915
17182
|
continue;
|
|
16916
17183
|
const sessionId = sessionData.id;
|
|
16917
|
-
const sessionMsgDir =
|
|
17184
|
+
const sessionMsgDir = join11(messageDir, sessionId);
|
|
16918
17185
|
const prompts = [];
|
|
16919
17186
|
const responses = [];
|
|
16920
17187
|
const toolsUsed = new Set;
|
|
@@ -16925,12 +17192,12 @@ function collectOpenCodeSessions2(openCodeDir, since, until) {
|
|
|
16925
17192
|
let model = "unknown";
|
|
16926
17193
|
let startTime = createdAt;
|
|
16927
17194
|
let endTime = updatedAt;
|
|
16928
|
-
if (
|
|
17195
|
+
if (existsSync11(sessionMsgDir)) {
|
|
16929
17196
|
const msgFiles = readdirSync5(sessionMsgDir).filter((f3) => f3.endsWith(".json")).sort();
|
|
16930
17197
|
for (const msgFile of msgFiles) {
|
|
16931
17198
|
try {
|
|
16932
|
-
const msgPath =
|
|
16933
|
-
const msgData = JSON.parse(
|
|
17199
|
+
const msgPath = join11(sessionMsgDir, msgFile);
|
|
17200
|
+
const msgData = JSON.parse(readFileSync11(msgPath, "utf-8"));
|
|
16934
17201
|
const msgId = msgData.id;
|
|
16935
17202
|
if (msgData.model?.modelID) {
|
|
16936
17203
|
model = msgData.model.modelID;
|
|
@@ -16940,14 +17207,14 @@ function collectOpenCodeSessions2(openCodeDir, since, until) {
|
|
|
16940
17207
|
startTime = msgTime;
|
|
16941
17208
|
if (msgTime > endTime)
|
|
16942
17209
|
endTime = msgTime;
|
|
16943
|
-
const msgPartDir =
|
|
17210
|
+
const msgPartDir = join11(partDir, msgId);
|
|
16944
17211
|
let messageText = "";
|
|
16945
|
-
if (
|
|
17212
|
+
if (existsSync11(msgPartDir)) {
|
|
16946
17213
|
const partFiles = readdirSync5(msgPartDir).filter((f3) => f3.endsWith(".json")).sort();
|
|
16947
17214
|
for (const partFile of partFiles) {
|
|
16948
17215
|
try {
|
|
16949
|
-
const partPath =
|
|
16950
|
-
const partData = JSON.parse(
|
|
17216
|
+
const partPath = join11(msgPartDir, partFile);
|
|
17217
|
+
const partData = JSON.parse(readFileSync11(partPath, "utf-8"));
|
|
16951
17218
|
if (partData.type === "text" && partData.text && !partData.synthetic) {
|
|
16952
17219
|
messageText += partData.text + `
|
|
16953
17220
|
`;
|
|
@@ -17121,10 +17388,10 @@ function analyzeResponse(text, sessionId, index, promptId, timestamp) {
|
|
|
17121
17388
|
}
|
|
17122
17389
|
function collectMCPConfigs() {
|
|
17123
17390
|
const configs = [];
|
|
17124
|
-
const claudeConfig =
|
|
17125
|
-
if (
|
|
17391
|
+
const claudeConfig = join11(homedir9(), ".claude.json");
|
|
17392
|
+
if (existsSync11(claudeConfig)) {
|
|
17126
17393
|
try {
|
|
17127
|
-
const data = JSON.parse(
|
|
17394
|
+
const data = JSON.parse(readFileSync11(claudeConfig, "utf-8"));
|
|
17128
17395
|
const mcpServers = data.mcpServers || {};
|
|
17129
17396
|
for (const [name, config] of Object.entries(mcpServers)) {
|
|
17130
17397
|
configs.push({
|
|
@@ -17137,13 +17404,13 @@ function collectMCPConfigs() {
|
|
|
17137
17404
|
} catch {}
|
|
17138
17405
|
}
|
|
17139
17406
|
const openCodeConfigs = [
|
|
17140
|
-
|
|
17141
|
-
|
|
17407
|
+
join11(homedir9(), ".opencode.json"),
|
|
17408
|
+
join11(homedir9(), ".config", "opencode", "opencode.json")
|
|
17142
17409
|
];
|
|
17143
17410
|
for (const configPath of openCodeConfigs) {
|
|
17144
|
-
if (
|
|
17411
|
+
if (existsSync11(configPath)) {
|
|
17145
17412
|
try {
|
|
17146
|
-
const data = JSON.parse(
|
|
17413
|
+
const data = JSON.parse(readFileSync11(configPath, "utf-8"));
|
|
17147
17414
|
const mcpServers = data.mcp || {};
|
|
17148
17415
|
for (const [name, config] of Object.entries(mcpServers)) {
|
|
17149
17416
|
if (!configs.find((c3) => c3.name === name)) {
|
|
@@ -17158,10 +17425,10 @@ function collectMCPConfigs() {
|
|
|
17158
17425
|
} catch {}
|
|
17159
17426
|
}
|
|
17160
17427
|
}
|
|
17161
|
-
const cursorConfig =
|
|
17162
|
-
if (
|
|
17428
|
+
const cursorConfig = join11(homedir9(), ".cursor", "mcp.json");
|
|
17429
|
+
if (existsSync11(cursorConfig)) {
|
|
17163
17430
|
try {
|
|
17164
|
-
const data = JSON.parse(
|
|
17431
|
+
const data = JSON.parse(readFileSync11(cursorConfig, "utf-8"));
|
|
17165
17432
|
const mcpServers = data.mcpServers || {};
|
|
17166
17433
|
for (const [name, config] of Object.entries(mcpServers)) {
|
|
17167
17434
|
if (!configs.find((c3) => c3.name === name)) {
|
|
@@ -19362,9 +19629,9 @@ function getSeverityEmoji(severity) {
|
|
|
19362
19629
|
}
|
|
19363
19630
|
|
|
19364
19631
|
// src/lib/tool-analyzer.ts
|
|
19365
|
-
import { existsSync as
|
|
19366
|
-
import { homedir as
|
|
19367
|
-
import { join as
|
|
19632
|
+
import { existsSync as existsSync12, readdirSync as readdirSync6 } from "node:fs";
|
|
19633
|
+
import { homedir as homedir10 } from "node:os";
|
|
19634
|
+
import { join as join12 } from "node:path";
|
|
19368
19635
|
function analyzeToolUtilization(data) {
|
|
19369
19636
|
const mcpServers = analyzeMCPServers(data);
|
|
19370
19637
|
const mcpSummary = buildMCPSummary(mcpServers);
|
|
@@ -19514,24 +19781,24 @@ function categorizeTools(tools) {
|
|
|
19514
19781
|
}
|
|
19515
19782
|
function analyzeSkills() {
|
|
19516
19783
|
const skills = [];
|
|
19517
|
-
const home =
|
|
19784
|
+
const home = homedir10();
|
|
19518
19785
|
const skillsDirs = [
|
|
19519
|
-
|
|
19520
|
-
|
|
19521
|
-
|
|
19786
|
+
join12(home, ".claude", "skills"),
|
|
19787
|
+
join12(home, ".agents", "skills"),
|
|
19788
|
+
join12(home, ".config", "claude", "skills")
|
|
19522
19789
|
];
|
|
19523
19790
|
const projectSkillsDirs = [
|
|
19524
|
-
|
|
19525
|
-
|
|
19791
|
+
join12(process.cwd(), ".claude", "skills"),
|
|
19792
|
+
join12(process.cwd(), ".agents", "skills")
|
|
19526
19793
|
];
|
|
19527
19794
|
const openCodeSkillDirs = [
|
|
19528
|
-
|
|
19529
|
-
|
|
19795
|
+
join12(home, ".config", "opencode", "skills"),
|
|
19796
|
+
join12(home, ".local", "share", "opencode", "skills")
|
|
19530
19797
|
];
|
|
19531
19798
|
const allSkillDirs = [...skillsDirs, ...projectSkillsDirs, ...openCodeSkillDirs];
|
|
19532
19799
|
const seenSkills = new Set;
|
|
19533
19800
|
for (const skillsDir of allSkillDirs) {
|
|
19534
|
-
if (
|
|
19801
|
+
if (existsSync12(skillsDir)) {
|
|
19535
19802
|
try {
|
|
19536
19803
|
const entries = readdirSync6(skillsDir, { withFileTypes: true });
|
|
19537
19804
|
for (const entry of entries) {
|
|
@@ -19542,7 +19809,7 @@ function analyzeSkills() {
|
|
|
19542
19809
|
if (entry.isDirectory() || entry.isSymbolicLink() || entry.name.endsWith(".md")) {
|
|
19543
19810
|
skills.push({
|
|
19544
19811
|
name: skillName,
|
|
19545
|
-
path:
|
|
19812
|
+
path: join12(skillsDir, entry.name),
|
|
19546
19813
|
used: false,
|
|
19547
19814
|
usageCount: 0
|
|
19548
19815
|
});
|
|
@@ -19839,22 +20106,22 @@ function renderToolUtilizationMarkdown(analysis) {
|
|
|
19839
20106
|
}
|
|
19840
20107
|
|
|
19841
20108
|
// src/lib/coverage-parser.ts
|
|
19842
|
-
import { existsSync as
|
|
19843
|
-
import { join as
|
|
20109
|
+
import { existsSync as existsSync13, readFileSync as readFileSync13 } from "node:fs";
|
|
20110
|
+
import { join as join13 } from "node:path";
|
|
19844
20111
|
function parseCoverageReport(projectDir) {
|
|
19845
20112
|
const coveragePaths = [
|
|
19846
|
-
{ path:
|
|
19847
|
-
{ path:
|
|
19848
|
-
{ path:
|
|
19849
|
-
{ path:
|
|
19850
|
-
{ path:
|
|
19851
|
-
{ path:
|
|
19852
|
-
{ path:
|
|
20113
|
+
{ path: join13(projectDir, "coverage", "lcov.info"), parser: parseLcov },
|
|
20114
|
+
{ path: join13(projectDir, "coverage", "coverage-summary.json"), parser: parseIstanbulSummary },
|
|
20115
|
+
{ path: join13(projectDir, "coverage", "coverage-final.json"), parser: parseIstanbulFinal },
|
|
20116
|
+
{ path: join13(projectDir, "coverage", "cobertura-coverage.xml"), parser: parseCobertura },
|
|
20117
|
+
{ path: join13(projectDir, "coverage", "clover.xml"), parser: parseClover },
|
|
20118
|
+
{ path: join13(projectDir, "lcov.info"), parser: parseLcov },
|
|
20119
|
+
{ path: join13(projectDir, ".nyc_output", "coverage-summary.json"), parser: parseIstanbulSummary }
|
|
19853
20120
|
];
|
|
19854
20121
|
for (const { path, parser: parser4 } of coveragePaths) {
|
|
19855
|
-
if (
|
|
20122
|
+
if (existsSync13(path)) {
|
|
19856
20123
|
try {
|
|
19857
|
-
const content =
|
|
20124
|
+
const content = readFileSync13(path, "utf-8");
|
|
19858
20125
|
return parser4(content, path);
|
|
19859
20126
|
} catch {}
|
|
19860
20127
|
}
|
|
@@ -21566,7 +21833,7 @@ function formatReportAsJSON(report) {
|
|
|
21566
21833
|
}
|
|
21567
21834
|
|
|
21568
21835
|
// src/commands/report.ts
|
|
21569
|
-
import { writeFileSync as
|
|
21836
|
+
import { writeFileSync as writeFileSync6 } from "node:fs";
|
|
21570
21837
|
import { resolve } from "node:path";
|
|
21571
21838
|
var reportCommand = defineCommand2({
|
|
21572
21839
|
meta: {
|
|
@@ -21778,7 +22045,7 @@ async function runHackathonReport(args) {
|
|
|
21778
22045
|
}
|
|
21779
22046
|
if (args.output) {
|
|
21780
22047
|
const filepath = resolve(projectDir, args.output);
|
|
21781
|
-
|
|
22048
|
+
writeFileSync6(filepath, output);
|
|
21782
22049
|
consola.success(`Report saved to ${filepath}`);
|
|
21783
22050
|
}
|
|
21784
22051
|
console.log(output);
|
|
@@ -21947,7 +22214,7 @@ async function runLeadershipReport(args) {
|
|
|
21947
22214
|
}
|
|
21948
22215
|
if (args.output) {
|
|
21949
22216
|
const filepath = resolve(projectDir, args.output);
|
|
21950
|
-
|
|
22217
|
+
writeFileSync6(filepath, output);
|
|
21951
22218
|
consola.success(`Report saved to ${filepath}`);
|
|
21952
22219
|
}
|
|
21953
22220
|
console.log(output);
|
|
@@ -22109,9 +22376,9 @@ function renderBar4(value, width) {
|
|
|
22109
22376
|
}
|
|
22110
22377
|
|
|
22111
22378
|
// src/commands/doctor.ts
|
|
22112
|
-
import { existsSync as
|
|
22113
|
-
import { homedir as
|
|
22114
|
-
import { join as
|
|
22379
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
22380
|
+
import { homedir as homedir11 } from "node:os";
|
|
22381
|
+
import { join as join14 } from "node:path";
|
|
22115
22382
|
init_client();
|
|
22116
22383
|
|
|
22117
22384
|
// src/lib/recommendations-db.ts
|
|
@@ -22237,6 +22504,18 @@ var PLUGINS = [
|
|
|
22237
22504
|
}
|
|
22238
22505
|
];
|
|
22239
22506
|
var SKILLS = [
|
|
22507
|
+
{
|
|
22508
|
+
id: "find-skills",
|
|
22509
|
+
name: "Find Skills",
|
|
22510
|
+
type: "skill",
|
|
22511
|
+
description: "Discover and install skills from the open agent skills ecosystem - essential for any AI workflow",
|
|
22512
|
+
installCommand: "npx skills add vercel-labs/skills@find-skills --yes",
|
|
22513
|
+
phases: ["requirements", "planning", "implementation", "review"],
|
|
22514
|
+
impact: "high",
|
|
22515
|
+
detectionKey: "find-skills",
|
|
22516
|
+
website: "https://skills.sh/vercel-labs/skills/find-skills",
|
|
22517
|
+
badge: "Essential"
|
|
22518
|
+
},
|
|
22240
22519
|
{
|
|
22241
22520
|
id: "tdd-skill",
|
|
22242
22521
|
name: "Test-Driven Development",
|
|
@@ -22760,16 +23039,16 @@ var doctorCommand = defineCommand2({
|
|
|
22760
23039
|
results.push({ label: "OS", status: "info", value: `${process.platform} ${process.arch}` });
|
|
22761
23040
|
results.push({ label: "Bun", status: "info", value: typeof Bun !== "undefined" ? Bun.version : "N/A" });
|
|
22762
23041
|
results.push({ label: "Node", status: "info", value: process.version });
|
|
22763
|
-
results.push({ label: "Home", status: "info", value:
|
|
22764
|
-
const gitDir =
|
|
22765
|
-
if (
|
|
23042
|
+
results.push({ label: "Home", status: "info", value: homedir11() });
|
|
23043
|
+
const gitDir = join14(process.cwd(), ".git");
|
|
23044
|
+
if (existsSync14(gitDir)) {
|
|
22766
23045
|
results.push({ label: "Git", status: "success", value: "Repository detected" });
|
|
22767
23046
|
} else {
|
|
22768
23047
|
results.push({ label: "Git", status: "warn", value: "No repository in current directory" });
|
|
22769
23048
|
}
|
|
22770
23049
|
for (const [agent, pathTemplate] of Object.entries(AGENT_LOG_PATHS)) {
|
|
22771
|
-
const resolvedPath = pathTemplate.replace("~",
|
|
22772
|
-
if (
|
|
23050
|
+
const resolvedPath = pathTemplate.replace("~", homedir11());
|
|
23051
|
+
if (existsSync14(resolvedPath)) {
|
|
22773
23052
|
results.push({ label: agent, status: "success", value: `found at ${resolvedPath}` });
|
|
22774
23053
|
}
|
|
22775
23054
|
}
|
|
@@ -22823,10 +23102,10 @@ var doctorCommand = defineCommand2({
|
|
|
22823
23102
|
});
|
|
22824
23103
|
|
|
22825
23104
|
// src/commands/setup.ts
|
|
22826
|
-
import { existsSync as
|
|
22827
|
-
import { join as
|
|
22828
|
-
import { homedir as
|
|
22829
|
-
import { execSync as
|
|
23105
|
+
import { existsSync as existsSync15, readFileSync as readFileSync14, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, copyFileSync } from "node:fs";
|
|
23106
|
+
import { join as join15, dirname as dirname2 } from "node:path";
|
|
23107
|
+
import { homedir as homedir12, platform as platform2 } from "node:os";
|
|
23108
|
+
import { execSync as execSync4 } from "node:child_process";
|
|
22830
23109
|
import { createInterface } from "node:readline";
|
|
22831
23110
|
var CONVEX_SITE_URL = "https://steady-bass-841.convex.site";
|
|
22832
23111
|
async function fetchSetupData() {
|
|
@@ -22844,7 +23123,7 @@ var FALLBACK_HARNESSES = [
|
|
|
22844
23123
|
id: "claude-code",
|
|
22845
23124
|
name: "Claude Code",
|
|
22846
23125
|
configPaths: [
|
|
22847
|
-
|
|
23126
|
+
join15(homedir12(), ".claude.json")
|
|
22848
23127
|
],
|
|
22849
23128
|
mcpConfigKey: "mcpServers",
|
|
22850
23129
|
detected: false
|
|
@@ -22853,8 +23132,8 @@ var FALLBACK_HARNESSES = [
|
|
|
22853
23132
|
id: "opencode",
|
|
22854
23133
|
name: "OpenCode",
|
|
22855
23134
|
configPaths: [
|
|
22856
|
-
|
|
22857
|
-
|
|
23135
|
+
join15(homedir12(), ".opencode.json"),
|
|
23136
|
+
join15(homedir12(), ".config", "opencode", "opencode.json")
|
|
22858
23137
|
],
|
|
22859
23138
|
mcpConfigKey: "mcp",
|
|
22860
23139
|
detected: false
|
|
@@ -22863,8 +23142,8 @@ var FALLBACK_HARNESSES = [
|
|
|
22863
23142
|
id: "cursor",
|
|
22864
23143
|
name: "Cursor",
|
|
22865
23144
|
configPaths: [
|
|
22866
|
-
|
|
22867
|
-
|
|
23145
|
+
join15(homedir12(), ".cursor", "mcp.json"),
|
|
23146
|
+
join15(homedir12(), "Library", "Application Support", "Cursor", "User", "globalStorage", "mcp.json")
|
|
22868
23147
|
],
|
|
22869
23148
|
mcpConfigKey: "mcpServers",
|
|
22870
23149
|
detected: false
|
|
@@ -22881,7 +23160,7 @@ function getConfigPathsForPlatform(harness) {
|
|
|
22881
23160
|
} else {
|
|
22882
23161
|
paths = pathMap.linux;
|
|
22883
23162
|
}
|
|
22884
|
-
return paths.map((p) => p.replace(/^~/,
|
|
23163
|
+
return paths.map((p) => p.replace(/^~/, homedir12()).replace(/%USERPROFILE%/gi, homedir12()).replace(/%APPDATA%/gi, join15(homedir12(), "AppData", "Roaming")));
|
|
22885
23164
|
}
|
|
22886
23165
|
function convertAPIHarnessToConfig(harness) {
|
|
22887
23166
|
return {
|
|
@@ -22896,7 +23175,7 @@ function detectHarnesses(harnesses) {
|
|
|
22896
23175
|
const detected = [];
|
|
22897
23176
|
for (const harness of harnesses) {
|
|
22898
23177
|
for (const configPath of harness.configPaths) {
|
|
22899
|
-
if (
|
|
23178
|
+
if (existsSync15(configPath)) {
|
|
22900
23179
|
detected.push({
|
|
22901
23180
|
...harness,
|
|
22902
23181
|
detected: true,
|
|
@@ -22909,19 +23188,19 @@ function detectHarnesses(harnesses) {
|
|
|
22909
23188
|
return detected;
|
|
22910
23189
|
}
|
|
22911
23190
|
function backupConfig(configPath) {
|
|
22912
|
-
const backupDir =
|
|
22913
|
-
if (!
|
|
22914
|
-
|
|
23191
|
+
const backupDir = join15(homedir12(), ".nairon", "backups");
|
|
23192
|
+
if (!existsSync15(backupDir)) {
|
|
23193
|
+
mkdirSync6(backupDir, { recursive: true });
|
|
22915
23194
|
}
|
|
22916
23195
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
22917
23196
|
const filename = configPath.replace(/[/\\]/g, "_").replace(/^_/, "");
|
|
22918
|
-
const backupPath =
|
|
23197
|
+
const backupPath = join15(backupDir, `${timestamp}_${filename}`);
|
|
22919
23198
|
copyFileSync(configPath, backupPath);
|
|
22920
23199
|
return backupPath;
|
|
22921
23200
|
}
|
|
22922
23201
|
function readJsonConfig(configPath) {
|
|
22923
23202
|
try {
|
|
22924
|
-
const content =
|
|
23203
|
+
const content = readFileSync14(configPath, "utf-8");
|
|
22925
23204
|
return JSON.parse(content);
|
|
22926
23205
|
} catch {
|
|
22927
23206
|
return {};
|
|
@@ -22929,10 +23208,10 @@ function readJsonConfig(configPath) {
|
|
|
22929
23208
|
}
|
|
22930
23209
|
function writeJsonConfig(configPath, config) {
|
|
22931
23210
|
const dir = dirname2(configPath);
|
|
22932
|
-
if (!
|
|
22933
|
-
|
|
23211
|
+
if (!existsSync15(dir)) {
|
|
23212
|
+
mkdirSync6(dir, { recursive: true });
|
|
22934
23213
|
}
|
|
22935
|
-
|
|
23214
|
+
writeFileSync7(configPath, JSON.stringify(config, null, 2));
|
|
22936
23215
|
}
|
|
22937
23216
|
async function prompt2(question) {
|
|
22938
23217
|
const rl = createInterface({
|
|
@@ -22973,7 +23252,7 @@ function getInstalledMCPs(harnesses) {
|
|
|
22973
23252
|
const installed = new Set;
|
|
22974
23253
|
for (const harness of harnesses) {
|
|
22975
23254
|
for (const configPath of harness.configPaths) {
|
|
22976
|
-
if (!
|
|
23255
|
+
if (!existsSync15(configPath))
|
|
22977
23256
|
continue;
|
|
22978
23257
|
const config = readJsonConfig(configPath);
|
|
22979
23258
|
const mcpServers = config[harness.mcpConfigKey];
|
|
@@ -22997,7 +23276,7 @@ async function installMCPServer(serverName, instruction, harness) {
|
|
|
22997
23276
|
if (!harness.configPath || !instruction.mcpServerConfig)
|
|
22998
23277
|
return false;
|
|
22999
23278
|
try {
|
|
23000
|
-
if (
|
|
23279
|
+
if (existsSync15(harness.configPath)) {
|
|
23001
23280
|
backupConfig(harness.configPath);
|
|
23002
23281
|
}
|
|
23003
23282
|
const config = readJsonConfig(harness.configPath);
|
|
@@ -23025,16 +23304,16 @@ async function installMCPServer(serverName, instruction, harness) {
|
|
|
23025
23304
|
async function installBeads(projectDir) {
|
|
23026
23305
|
try {
|
|
23027
23306
|
try {
|
|
23028
|
-
|
|
23307
|
+
execSync4("bd --version", { stdio: "ignore" });
|
|
23029
23308
|
} catch {
|
|
23030
23309
|
const spinner = createSpinner("Installing Beads globally...");
|
|
23031
23310
|
spinner.start();
|
|
23032
23311
|
try {
|
|
23033
|
-
|
|
23312
|
+
execSync4("bun add -g beads", { stdio: "ignore" });
|
|
23034
23313
|
spinner.succeed("Beads installed globally");
|
|
23035
23314
|
} catch {
|
|
23036
23315
|
try {
|
|
23037
|
-
|
|
23316
|
+
execSync4("npm install -g beads", { stdio: "ignore" });
|
|
23038
23317
|
spinner.succeed("Beads installed globally (via npm)");
|
|
23039
23318
|
} catch {
|
|
23040
23319
|
spinner.fail("Failed to install Beads globally");
|
|
@@ -23042,13 +23321,13 @@ async function installBeads(projectDir) {
|
|
|
23042
23321
|
}
|
|
23043
23322
|
}
|
|
23044
23323
|
}
|
|
23045
|
-
const beadsDir =
|
|
23046
|
-
if (!
|
|
23324
|
+
const beadsDir = join15(projectDir, ".beads");
|
|
23325
|
+
if (!existsSync15(beadsDir)) {
|
|
23047
23326
|
const projectName = projectDir.split(/[/\\]/).pop() ?? "project";
|
|
23048
23327
|
const initSpinner = createSpinner(`Initializing Beads in ${projectName}...`);
|
|
23049
23328
|
initSpinner.start();
|
|
23050
23329
|
try {
|
|
23051
|
-
|
|
23330
|
+
execSync4(`bd init ${projectName}`, { cwd: projectDir, stdio: "ignore" });
|
|
23052
23331
|
initSpinner.succeed(`Beads initialized in ${projectName}`);
|
|
23053
23332
|
} catch {
|
|
23054
23333
|
initSpinner.fail("Failed to initialize Beads in project");
|
|
@@ -23062,9 +23341,9 @@ async function installBeads(projectDir) {
|
|
|
23062
23341
|
}
|
|
23063
23342
|
}
|
|
23064
23343
|
async function createClaudeRules(projectDir) {
|
|
23065
|
-
const claudeMdPath =
|
|
23066
|
-
const agentsMdPath =
|
|
23067
|
-
if (
|
|
23344
|
+
const claudeMdPath = join15(projectDir, "CLAUDE.md");
|
|
23345
|
+
const agentsMdPath = join15(projectDir, "AGENTS.md");
|
|
23346
|
+
if (existsSync15(claudeMdPath) || existsSync15(agentsMdPath)) {
|
|
23068
23347
|
console.log(` ${icons.info} CLAUDE.md or AGENTS.md already exists`);
|
|
23069
23348
|
return true;
|
|
23070
23349
|
}
|
|
@@ -23098,7 +23377,7 @@ bun run build
|
|
|
23098
23377
|
Use conventional commits: feat:, fix:, docs:, refactor:, test:, chore:
|
|
23099
23378
|
`;
|
|
23100
23379
|
try {
|
|
23101
|
-
|
|
23380
|
+
writeFileSync7(claudeMdPath, content);
|
|
23102
23381
|
return true;
|
|
23103
23382
|
} catch {
|
|
23104
23383
|
return false;
|
|
@@ -23378,7 +23657,7 @@ var setupCommand = defineCommand2({
|
|
|
23378
23657
|
});
|
|
23379
23658
|
|
|
23380
23659
|
// src/commands/upgrade.ts
|
|
23381
|
-
import { execSync as
|
|
23660
|
+
import { execSync as execSync5 } from "node:child_process";
|
|
23382
23661
|
var CYAN = "\x1B[36m";
|
|
23383
23662
|
var GREEN = "\x1B[32m";
|
|
23384
23663
|
var YELLOW = "\x1B[33m";
|
|
@@ -23387,6 +23666,17 @@ var BOLD = "\x1B[1m";
|
|
|
23387
23666
|
var RESET = "\x1B[0m";
|
|
23388
23667
|
var MAGENTA = "\x1B[35m";
|
|
23389
23668
|
var CHANGELOG = [
|
|
23669
|
+
{
|
|
23670
|
+
version: "0.5.1",
|
|
23671
|
+
date: "2026-02-14",
|
|
23672
|
+
title: "Smart Project Onboarding",
|
|
23673
|
+
highlights: [
|
|
23674
|
+
"First scan detects your project and suggests relevant skills",
|
|
23675
|
+
"Auto-installs find-skills to discover more tools later",
|
|
23676
|
+
"Analyzes README to recommend skills for your tech stack",
|
|
23677
|
+
"Detects your AI agent (Claude Code, OpenCode, Cursor)"
|
|
23678
|
+
]
|
|
23679
|
+
},
|
|
23390
23680
|
{
|
|
23391
23681
|
version: "0.5.0",
|
|
23392
23682
|
date: "2026-02-14",
|
|
@@ -23703,7 +23993,7 @@ var upgradeCommand = defineCommand2({
|
|
|
23703
23993
|
console.log(`${DIM} Checking for updates...${RESET}`);
|
|
23704
23994
|
let latestVersion;
|
|
23705
23995
|
try {
|
|
23706
|
-
latestVersion =
|
|
23996
|
+
latestVersion = execSync5("npm view nairon-bench version", { encoding: "utf-8" }).trim();
|
|
23707
23997
|
} catch {
|
|
23708
23998
|
console.log(` ${YELLOW}⚠${RESET} Could not check npm registry`);
|
|
23709
23999
|
console.log(` ${DIM}Run 'bun add -g nairon-bench@latest' manually${RESET}`);
|
|
@@ -23730,7 +24020,7 @@ var upgradeCommand = defineCommand2({
|
|
|
23730
24020
|
console.log(` ${CYAN}↓${RESET} Upgrading to ${GREEN}v${latestVersion}${RESET}...`);
|
|
23731
24021
|
console.log();
|
|
23732
24022
|
try {
|
|
23733
|
-
|
|
24023
|
+
execSync5("npm install -g nairon-bench@latest", {
|
|
23734
24024
|
stdio: "inherit",
|
|
23735
24025
|
env: { ...process.env, npm_config_fund: "false" }
|
|
23736
24026
|
});
|
|
@@ -23748,7 +24038,7 @@ var upgradeCommand = defineCommand2({
|
|
|
23748
24038
|
});
|
|
23749
24039
|
function getCurrentVersion() {
|
|
23750
24040
|
try {
|
|
23751
|
-
const output =
|
|
24041
|
+
const output = execSync5("nb --version 2>/dev/null || nairon-bench --version 2>/dev/null", {
|
|
23752
24042
|
encoding: "utf-8",
|
|
23753
24043
|
stdio: ["pipe", "pipe", "pipe"]
|
|
23754
24044
|
});
|
|
@@ -23837,7 +24127,7 @@ function showFullChangelog() {
|
|
|
23837
24127
|
// package.json
|
|
23838
24128
|
var package_default = {
|
|
23839
24129
|
name: "nairon-bench",
|
|
23840
|
-
version: "0.5.
|
|
24130
|
+
version: "0.5.1",
|
|
23841
24131
|
description: "AI workflow benchmarking CLI",
|
|
23842
24132
|
type: "module",
|
|
23843
24133
|
bin: {
|
|
@@ -23845,7 +24135,8 @@ var package_default = {
|
|
|
23845
24135
|
nb: "./dist/index.js"
|
|
23846
24136
|
},
|
|
23847
24137
|
files: [
|
|
23848
|
-
"dist"
|
|
24138
|
+
"dist",
|
|
24139
|
+
"postinstall.js"
|
|
23849
24140
|
],
|
|
23850
24141
|
repository: {
|
|
23851
24142
|
type: "git",
|
|
@@ -23873,7 +24164,8 @@ var package_default = {
|
|
|
23873
24164
|
"test:e2e": "vitest run tests/e2e/",
|
|
23874
24165
|
"test:watch": "vitest",
|
|
23875
24166
|
clean: "rm -rf dist",
|
|
23876
|
-
prepublishOnly: "bun run build"
|
|
24167
|
+
prepublishOnly: "bun run build",
|
|
24168
|
+
postinstall: "node postinstall.js || true"
|
|
23877
24169
|
},
|
|
23878
24170
|
dependencies: {
|
|
23879
24171
|
"cli-boxes": "^4.0.1",
|
|
@@ -23896,9 +24188,9 @@ var versionCommand = defineCommand2({
|
|
|
23896
24188
|
|
|
23897
24189
|
// src/commands/init.ts
|
|
23898
24190
|
init_dist();
|
|
23899
|
-
import { existsSync as
|
|
23900
|
-
import { homedir as
|
|
23901
|
-
import { join as
|
|
24191
|
+
import { existsSync as existsSync16 } from "node:fs";
|
|
24192
|
+
import { homedir as homedir13, platform as platform3, arch } from "node:os";
|
|
24193
|
+
import { join as join16 } from "node:path";
|
|
23902
24194
|
init_client();
|
|
23903
24195
|
|
|
23904
24196
|
// src/lib/github-auth.ts
|
|
@@ -24068,8 +24360,8 @@ var initCommand = defineCommand2({
|
|
|
24068
24360
|
consola.start("Step 2/6: Detecting AI agents...");
|
|
24069
24361
|
const detectedAgents = [];
|
|
24070
24362
|
for (const [agent, pathTemplate] of Object.entries(AGENT_LOG_PATHS)) {
|
|
24071
|
-
const resolvedPath = pathTemplate.replace("~",
|
|
24072
|
-
if (
|
|
24363
|
+
const resolvedPath = pathTemplate.replace("~", homedir13());
|
|
24364
|
+
if (existsSync16(resolvedPath)) {
|
|
24073
24365
|
detectedAgents.push(agent);
|
|
24074
24366
|
consola.success(` Found: ${agent}`);
|
|
24075
24367
|
}
|
|
@@ -24172,7 +24464,7 @@ var initCommand = defineCommand2({
|
|
|
24172
24464
|
{ name: "playwright", configs: ["playwright.config.ts", "playwright.config.js"] }
|
|
24173
24465
|
];
|
|
24174
24466
|
for (const fw of testFrameworks) {
|
|
24175
|
-
if (fw.configs.some((c3) =>
|
|
24467
|
+
if (fw.configs.some((c3) => existsSync16(join16(process.cwd(), c3)))) {
|
|
24176
24468
|
toolStack.testing.push(fw.name);
|
|
24177
24469
|
}
|
|
24178
24470
|
}
|
|
@@ -24241,13 +24533,13 @@ var initCommand = defineCommand2({
|
|
|
24241
24533
|
});
|
|
24242
24534
|
function detectPackageManager() {
|
|
24243
24535
|
const cwd = process.cwd();
|
|
24244
|
-
if (
|
|
24536
|
+
if (existsSync16(join16(cwd, "bun.lock")) || existsSync16(join16(cwd, "bun.lockb")))
|
|
24245
24537
|
return "bun";
|
|
24246
|
-
if (
|
|
24538
|
+
if (existsSync16(join16(cwd, "pnpm-lock.yaml")))
|
|
24247
24539
|
return "pnpm";
|
|
24248
|
-
if (
|
|
24540
|
+
if (existsSync16(join16(cwd, "yarn.lock")))
|
|
24249
24541
|
return "yarn";
|
|
24250
|
-
if (
|
|
24542
|
+
if (existsSync16(join16(cwd, "package-lock.json")))
|
|
24251
24543
|
return "npm";
|
|
24252
24544
|
return;
|
|
24253
24545
|
}
|
|
@@ -24262,15 +24554,15 @@ var CLAUDE_CODE_SKILLS = [
|
|
|
24262
24554
|
];
|
|
24263
24555
|
function detectEasyWins(detectedAgents) {
|
|
24264
24556
|
const wins = [];
|
|
24265
|
-
const home =
|
|
24557
|
+
const home = homedir13();
|
|
24266
24558
|
const hasClaudeCode = detectedAgents.some((a2) => a2.toLowerCase().includes("claude") || a2.toLowerCase().includes("opencode"));
|
|
24267
|
-
const claudeConfigDir =
|
|
24268
|
-
const hasClaudeConfig =
|
|
24559
|
+
const claudeConfigDir = join16(home, ".claude");
|
|
24560
|
+
const hasClaudeConfig = existsSync16(claudeConfigDir);
|
|
24269
24561
|
if (hasClaudeCode || hasClaudeConfig) {
|
|
24270
|
-
const skillsDir =
|
|
24562
|
+
const skillsDir = join16(home, ".claude", "skills");
|
|
24271
24563
|
for (const skill of CLAUDE_CODE_SKILLS) {
|
|
24272
|
-
const skillPath =
|
|
24273
|
-
const isInstalled =
|
|
24564
|
+
const skillPath = join16(skillsDir, skill.id);
|
|
24565
|
+
const isInstalled = existsSync16(skillPath);
|
|
24274
24566
|
if (!isInstalled) {
|
|
24275
24567
|
wins.push({
|
|
24276
24568
|
icon: skill.icon,
|
|
@@ -24286,12 +24578,12 @@ function detectEasyWins(detectedAgents) {
|
|
|
24286
24578
|
// src/commands/onboard.ts
|
|
24287
24579
|
init_dist();
|
|
24288
24580
|
init_client();
|
|
24289
|
-
import { existsSync as
|
|
24290
|
-
import { join as
|
|
24581
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync7, readFileSync as readFileSync16, writeFileSync as writeFileSync8, readdirSync as readdirSync9 } from "node:fs";
|
|
24582
|
+
import { join as join18 } from "node:path";
|
|
24291
24583
|
|
|
24292
24584
|
// src/lib/project-context-detector.ts
|
|
24293
|
-
import { existsSync as
|
|
24294
|
-
import { join as
|
|
24585
|
+
import { existsSync as existsSync17, readFileSync as readFileSync15, readdirSync as readdirSync8 } from "node:fs";
|
|
24586
|
+
import { join as join17, basename as basename4 } from "node:path";
|
|
24295
24587
|
function detectProjectContext(projectDir) {
|
|
24296
24588
|
const projectName = basename4(projectDir);
|
|
24297
24589
|
const projectId = generateProjectId(projectDir);
|
|
@@ -24327,11 +24619,11 @@ function detectTechStack(projectDir) {
|
|
|
24327
24619
|
};
|
|
24328
24620
|
}
|
|
24329
24621
|
function readPackageJson(projectDir) {
|
|
24330
|
-
const pkgPath =
|
|
24331
|
-
if (!
|
|
24622
|
+
const pkgPath = join17(projectDir, "package.json");
|
|
24623
|
+
if (!existsSync17(pkgPath))
|
|
24332
24624
|
return {};
|
|
24333
24625
|
try {
|
|
24334
|
-
return JSON.parse(
|
|
24626
|
+
return JSON.parse(readFileSync15(pkgPath, "utf-8"));
|
|
24335
24627
|
} catch {
|
|
24336
24628
|
return {};
|
|
24337
24629
|
}
|
|
@@ -24352,34 +24644,34 @@ function detectFramework(deps) {
|
|
|
24352
24644
|
return null;
|
|
24353
24645
|
}
|
|
24354
24646
|
function detectMetaFramework(deps, projectDir) {
|
|
24355
|
-
if (deps.next ||
|
|
24647
|
+
if (deps.next || existsSync17(join17(projectDir, "next.config.js")) || existsSync17(join17(projectDir, "next.config.mjs")))
|
|
24356
24648
|
return "next";
|
|
24357
|
-
if (deps.nuxt ||
|
|
24649
|
+
if (deps.nuxt || existsSync17(join17(projectDir, "nuxt.config.ts")))
|
|
24358
24650
|
return "nuxt";
|
|
24359
24651
|
if (deps["@sveltejs/kit"])
|
|
24360
24652
|
return "sveltekit";
|
|
24361
|
-
if (deps.astro ||
|
|
24653
|
+
if (deps.astro || existsSync17(join17(projectDir, "astro.config.mjs")))
|
|
24362
24654
|
return "astro";
|
|
24363
24655
|
if (deps["@remix-run/react"])
|
|
24364
24656
|
return "remix";
|
|
24365
24657
|
if (deps.gatsby)
|
|
24366
24658
|
return "gatsby";
|
|
24367
|
-
if (deps.vite ||
|
|
24659
|
+
if (deps.vite || existsSync17(join17(projectDir, "vite.config.ts")))
|
|
24368
24660
|
return "vite";
|
|
24369
24661
|
return null;
|
|
24370
24662
|
}
|
|
24371
24663
|
function detectRuntime(projectDir) {
|
|
24372
|
-
if (
|
|
24664
|
+
if (existsSync17(join17(projectDir, "bun.lockb")) || existsSync17(join17(projectDir, "bun.lock")))
|
|
24373
24665
|
return "bun";
|
|
24374
|
-
if (
|
|
24666
|
+
if (existsSync17(join17(projectDir, "deno.json")) || existsSync17(join17(projectDir, "deno.lock")))
|
|
24375
24667
|
return "deno";
|
|
24376
24668
|
return "node";
|
|
24377
24669
|
}
|
|
24378
24670
|
function detectLanguage(projectDir) {
|
|
24379
|
-
if (
|
|
24671
|
+
if (existsSync17(join17(projectDir, "tsconfig.json")))
|
|
24380
24672
|
return "typescript";
|
|
24381
|
-
const srcDir =
|
|
24382
|
-
if (
|
|
24673
|
+
const srcDir = join17(projectDir, "src");
|
|
24674
|
+
if (existsSync17(srcDir)) {
|
|
24383
24675
|
try {
|
|
24384
24676
|
const files = readdirSync8(srcDir);
|
|
24385
24677
|
if (files.some((f3) => f3.endsWith(".ts") || f3.endsWith(".tsx")))
|
|
@@ -24390,7 +24682,7 @@ function detectLanguage(projectDir) {
|
|
|
24390
24682
|
}
|
|
24391
24683
|
function detectStyling(deps, projectDir) {
|
|
24392
24684
|
const tools = [];
|
|
24393
|
-
if (deps.tailwindcss ||
|
|
24685
|
+
if (deps.tailwindcss || existsSync17(join17(projectDir, "tailwind.config.js")) || existsSync17(join17(projectDir, "tailwind.config.ts")))
|
|
24394
24686
|
tools.push("tailwind");
|
|
24395
24687
|
if (deps["styled-components"])
|
|
24396
24688
|
tools.push("styled-components");
|
|
@@ -24435,13 +24727,13 @@ function detectORM(deps) {
|
|
|
24435
24727
|
}
|
|
24436
24728
|
function detectTesting(deps, projectDir) {
|
|
24437
24729
|
const tools = [];
|
|
24438
|
-
if (deps.vitest ||
|
|
24730
|
+
if (deps.vitest || existsSync17(join17(projectDir, "vitest.config.ts")))
|
|
24439
24731
|
tools.push("vitest");
|
|
24440
|
-
if (deps.jest ||
|
|
24732
|
+
if (deps.jest || existsSync17(join17(projectDir, "jest.config.js")))
|
|
24441
24733
|
tools.push("jest");
|
|
24442
|
-
if (deps["@playwright/test"] ||
|
|
24734
|
+
if (deps["@playwright/test"] || existsSync17(join17(projectDir, "playwright.config.ts")))
|
|
24443
24735
|
tools.push("playwright");
|
|
24444
|
-
if (deps.cypress ||
|
|
24736
|
+
if (deps.cypress || existsSync17(join17(projectDir, "cypress.config.ts")))
|
|
24445
24737
|
tools.push("cypress");
|
|
24446
24738
|
if (deps["@testing-library/react"] || deps["@testing-library/vue"])
|
|
24447
24739
|
tools.push("testing-library");
|
|
@@ -24473,7 +24765,7 @@ function detectBuildTools(deps, projectDir) {
|
|
|
24473
24765
|
tools.push("esbuild");
|
|
24474
24766
|
if (deps.webpack)
|
|
24475
24767
|
tools.push("webpack");
|
|
24476
|
-
if (deps.turbo ||
|
|
24768
|
+
if (deps.turbo || existsSync17(join17(projectDir, "turbo.json")))
|
|
24477
24769
|
tools.push("turborepo");
|
|
24478
24770
|
if (deps.tsup)
|
|
24479
24771
|
tools.push("tsup");
|
|
@@ -24483,17 +24775,17 @@ function detectBuildTools(deps, projectDir) {
|
|
|
24483
24775
|
}
|
|
24484
24776
|
function detectDeployment(projectDir) {
|
|
24485
24777
|
const tools = [];
|
|
24486
|
-
if (
|
|
24778
|
+
if (existsSync17(join17(projectDir, "vercel.json")) || existsSync17(join17(projectDir, ".vercel")))
|
|
24487
24779
|
tools.push("vercel");
|
|
24488
|
-
if (
|
|
24780
|
+
if (existsSync17(join17(projectDir, "netlify.toml")))
|
|
24489
24781
|
tools.push("netlify");
|
|
24490
|
-
if (
|
|
24782
|
+
if (existsSync17(join17(projectDir, "fly.toml")))
|
|
24491
24783
|
tools.push("fly");
|
|
24492
|
-
if (
|
|
24784
|
+
if (existsSync17(join17(projectDir, "railway.json")))
|
|
24493
24785
|
tools.push("railway");
|
|
24494
|
-
if (
|
|
24786
|
+
if (existsSync17(join17(projectDir, "Dockerfile")))
|
|
24495
24787
|
tools.push("docker");
|
|
24496
|
-
if (
|
|
24788
|
+
if (existsSync17(join17(projectDir, ".github", "workflows")))
|
|
24497
24789
|
tools.push("github-actions");
|
|
24498
24790
|
return tools;
|
|
24499
24791
|
}
|
|
@@ -24516,20 +24808,20 @@ function detectAIML(deps) {
|
|
|
24516
24808
|
return tools;
|
|
24517
24809
|
}
|
|
24518
24810
|
function inferProjectType(projectDir, techStack) {
|
|
24519
|
-
if (
|
|
24811
|
+
if (existsSync17(join17(projectDir, "packages")) || existsSync17(join17(projectDir, "apps"))) {
|
|
24520
24812
|
return "monorepo";
|
|
24521
24813
|
}
|
|
24522
24814
|
const pkg = readPackageJson(projectDir);
|
|
24523
|
-
if (pkg.bin ||
|
|
24815
|
+
if (pkg.bin || existsSync17(join17(projectDir, "src", "cli.ts")) || existsSync17(join17(projectDir, "src", "index.ts"))) {
|
|
24524
24816
|
const hasBin = !!pkg.bin;
|
|
24525
|
-
const hasCommands =
|
|
24817
|
+
const hasCommands = existsSync17(join17(projectDir, "src", "commands"));
|
|
24526
24818
|
if (hasBin || hasCommands)
|
|
24527
24819
|
return "cli";
|
|
24528
24820
|
}
|
|
24529
24821
|
if (!techStack.framework && !techStack.metaFramework && pkg.main) {
|
|
24530
24822
|
return "library";
|
|
24531
24823
|
}
|
|
24532
|
-
if (
|
|
24824
|
+
if (existsSync17(join17(projectDir, "app.json")) || existsSync17(join17(projectDir, "expo"))) {
|
|
24533
24825
|
return "mobile";
|
|
24534
24826
|
}
|
|
24535
24827
|
if (techStack.database.length > 0 && !techStack.framework) {
|
|
@@ -24546,10 +24838,10 @@ function extractDescription(projectDir) {
|
|
|
24546
24838
|
return pkg.description;
|
|
24547
24839
|
const readmePaths = ["README.md", "readme.md", "Readme.md"];
|
|
24548
24840
|
for (const readme of readmePaths) {
|
|
24549
|
-
const path =
|
|
24550
|
-
if (
|
|
24841
|
+
const path = join17(projectDir, readme);
|
|
24842
|
+
if (existsSync17(path)) {
|
|
24551
24843
|
try {
|
|
24552
|
-
const content =
|
|
24844
|
+
const content = readFileSync15(path, "utf-8");
|
|
24553
24845
|
const lines = content.split(`
|
|
24554
24846
|
`);
|
|
24555
24847
|
let foundTitle = false;
|
|
@@ -25967,9 +26259,9 @@ var onboardCommand = defineCommand2({
|
|
|
25967
26259
|
},
|
|
25968
26260
|
async run({ args }) {
|
|
25969
26261
|
const projectPath = process.cwd();
|
|
25970
|
-
const contextPath =
|
|
25971
|
-
if (
|
|
25972
|
-
const existing = JSON.parse(
|
|
26262
|
+
const contextPath = join18(projectPath, ".nairon", "context.json");
|
|
26263
|
+
if (existsSync18(contextPath) && !args.force) {
|
|
26264
|
+
const existing = JSON.parse(readFileSync16(contextPath, "utf-8"));
|
|
25973
26265
|
consola.info("Project already onboarded. Use --force to re-run.");
|
|
25974
26266
|
consola.info(`Business: ${existing.businessContext?.domain || existing.businessContext?.slice?.(0, 50) || "Not set"}...`);
|
|
25975
26267
|
consola.info(`Stack: ${formatTechStackSummary(existing)}`);
|
|
@@ -26117,11 +26409,11 @@ var onboardCommand = defineCommand2({
|
|
|
26117
26409
|
createdAt: new Date().toISOString(),
|
|
26118
26410
|
updatedAt: new Date().toISOString()
|
|
26119
26411
|
};
|
|
26120
|
-
const naironDir =
|
|
26121
|
-
if (!
|
|
26122
|
-
|
|
26412
|
+
const naironDir = join18(projectPath, ".nairon");
|
|
26413
|
+
if (!existsSync18(naironDir)) {
|
|
26414
|
+
mkdirSync7(naironDir, { recursive: true });
|
|
26123
26415
|
}
|
|
26124
|
-
|
|
26416
|
+
writeFileSync8(contextPath, JSON.stringify(fullContext, null, 2));
|
|
26125
26417
|
consola.success(`Saved to ${contextPath}`);
|
|
26126
26418
|
if (isSupermemoryConfigured()) {
|
|
26127
26419
|
consola.start("Storing in Supermemory...");
|
|
@@ -26209,51 +26501,51 @@ function formatTechStackSummary(context) {
|
|
|
26209
26501
|
function detectInstalledTools(projectPath) {
|
|
26210
26502
|
const tools = [];
|
|
26211
26503
|
const home = process.env.HOME || "";
|
|
26212
|
-
const userClaudeJson =
|
|
26213
|
-
if (
|
|
26504
|
+
const userClaudeJson = join18(home, ".claude.json");
|
|
26505
|
+
if (existsSync18(userClaudeJson)) {
|
|
26214
26506
|
try {
|
|
26215
|
-
const config = JSON.parse(
|
|
26507
|
+
const config = JSON.parse(readFileSync16(userClaudeJson, "utf-8"));
|
|
26216
26508
|
if (config.mcpServers) {
|
|
26217
26509
|
tools.push(...Object.keys(config.mcpServers));
|
|
26218
26510
|
}
|
|
26219
26511
|
} catch {}
|
|
26220
26512
|
}
|
|
26221
|
-
const claudeDesktopConfig =
|
|
26222
|
-
if (
|
|
26513
|
+
const claudeDesktopConfig = join18(home, ".claude", "claude_desktop_config.json");
|
|
26514
|
+
if (existsSync18(claudeDesktopConfig)) {
|
|
26223
26515
|
try {
|
|
26224
|
-
const config = JSON.parse(
|
|
26516
|
+
const config = JSON.parse(readFileSync16(claudeDesktopConfig, "utf-8"));
|
|
26225
26517
|
if (config.mcpServers) {
|
|
26226
26518
|
tools.push(...Object.keys(config.mcpServers));
|
|
26227
26519
|
}
|
|
26228
26520
|
} catch {}
|
|
26229
26521
|
}
|
|
26230
|
-
const projectMcpJson =
|
|
26231
|
-
if (
|
|
26522
|
+
const projectMcpJson = join18(projectPath, ".mcp.json");
|
|
26523
|
+
if (existsSync18(projectMcpJson)) {
|
|
26232
26524
|
try {
|
|
26233
|
-
const config = JSON.parse(
|
|
26525
|
+
const config = JSON.parse(readFileSync16(projectMcpJson, "utf-8"));
|
|
26234
26526
|
if (config.mcpServers) {
|
|
26235
26527
|
tools.push(...Object.keys(config.mcpServers));
|
|
26236
26528
|
}
|
|
26237
26529
|
} catch {}
|
|
26238
26530
|
}
|
|
26239
|
-
const projectClaudeConfig =
|
|
26240
|
-
if (
|
|
26531
|
+
const projectClaudeConfig = join18(projectPath, ".claude", "settings.json");
|
|
26532
|
+
if (existsSync18(projectClaudeConfig)) {
|
|
26241
26533
|
try {
|
|
26242
|
-
const config = JSON.parse(
|
|
26534
|
+
const config = JSON.parse(readFileSync16(projectClaudeConfig, "utf-8"));
|
|
26243
26535
|
if (config.mcpServers) {
|
|
26244
26536
|
tools.push(...Object.keys(config.mcpServers));
|
|
26245
26537
|
}
|
|
26246
26538
|
} catch {}
|
|
26247
26539
|
}
|
|
26248
|
-
const skillsDir =
|
|
26249
|
-
if (
|
|
26540
|
+
const skillsDir = join18(home, ".config", "opencode", "skills");
|
|
26541
|
+
if (existsSync18(skillsDir)) {
|
|
26250
26542
|
try {
|
|
26251
26543
|
const skills = readdirSync9(skillsDir);
|
|
26252
26544
|
tools.push(...skills.filter((s2) => !s2.startsWith(".")));
|
|
26253
26545
|
} catch {}
|
|
26254
26546
|
}
|
|
26255
|
-
const agentsSkillsDir =
|
|
26256
|
-
if (
|
|
26547
|
+
const agentsSkillsDir = join18(home, ".agents", "skills");
|
|
26548
|
+
if (existsSync18(agentsSkillsDir)) {
|
|
26257
26549
|
try {
|
|
26258
26550
|
const skills = readdirSync9(agentsSkillsDir);
|
|
26259
26551
|
tools.push(...skills.filter((s2) => !s2.startsWith(".")));
|
|
@@ -26263,11 +26555,11 @@ function detectInstalledTools(projectPath) {
|
|
|
26263
26555
|
}
|
|
26264
26556
|
function detectPrimaryAgent() {
|
|
26265
26557
|
const home = process.env.HOME || "";
|
|
26266
|
-
if (
|
|
26558
|
+
if (existsSync18(join18(home, ".claude")))
|
|
26267
26559
|
return "claude-code";
|
|
26268
|
-
if (
|
|
26560
|
+
if (existsSync18(join18(home, ".cursor")))
|
|
26269
26561
|
return "cursor";
|
|
26270
|
-
if (
|
|
26562
|
+
if (existsSync18(join18(home, ".config", "opencode")))
|
|
26271
26563
|
return "opencode";
|
|
26272
26564
|
return;
|
|
26273
26565
|
}
|
|
@@ -26362,7 +26654,7 @@ function formatBytes(bytes) {
|
|
|
26362
26654
|
// package.json
|
|
26363
26655
|
var package_default2 = {
|
|
26364
26656
|
name: "nairon-bench",
|
|
26365
|
-
version: "0.5.
|
|
26657
|
+
version: "0.5.1",
|
|
26366
26658
|
description: "AI workflow benchmarking CLI",
|
|
26367
26659
|
type: "module",
|
|
26368
26660
|
bin: {
|
|
@@ -26370,7 +26662,8 @@ var package_default2 = {
|
|
|
26370
26662
|
nb: "./dist/index.js"
|
|
26371
26663
|
},
|
|
26372
26664
|
files: [
|
|
26373
|
-
"dist"
|
|
26665
|
+
"dist",
|
|
26666
|
+
"postinstall.js"
|
|
26374
26667
|
],
|
|
26375
26668
|
repository: {
|
|
26376
26669
|
type: "git",
|
|
@@ -26398,7 +26691,8 @@ var package_default2 = {
|
|
|
26398
26691
|
"test:e2e": "vitest run tests/e2e/",
|
|
26399
26692
|
"test:watch": "vitest",
|
|
26400
26693
|
clean: "rm -rf dist",
|
|
26401
|
-
prepublishOnly: "bun run build"
|
|
26694
|
+
prepublishOnly: "bun run build",
|
|
26695
|
+
postinstall: "node postinstall.js || true"
|
|
26402
26696
|
},
|
|
26403
26697
|
dependencies: {
|
|
26404
26698
|
"cli-boxes": "^4.0.1",
|
|
@@ -26463,7 +26757,7 @@ var hasVersion = args.includes("--version");
|
|
|
26463
26757
|
if (!hasSubcommand && !hasHelp && !hasVersion && args.length === 0) {
|
|
26464
26758
|
showBanner();
|
|
26465
26759
|
} else {
|
|
26466
|
-
const
|
|
26760
|
+
const cmd = defineCommand({
|
|
26467
26761
|
meta: {
|
|
26468
26762
|
name: "nairon-bench",
|
|
26469
26763
|
version: VERSION2,
|
|
@@ -26481,5 +26775,5 @@ if (!hasSubcommand && !hasHelp && !hasVersion && args.length === 0) {
|
|
|
26481
26775
|
cache: cacheCommand
|
|
26482
26776
|
}
|
|
26483
26777
|
});
|
|
26484
|
-
runMain(
|
|
26778
|
+
runMain(cmd);
|
|
26485
26779
|
}
|