nairon-bench 0.0.40 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +1029 -29
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -14181,6 +14181,11 @@ var scanCommand = defineCommand2({
14181
14181
  description: "Disable session caching (slower but ensures fresh data)",
14182
14182
  default: false
14183
14183
  },
14184
+ "no-recommend": {
14185
+ type: "boolean",
14186
+ description: "Skip showing recommendations after scan",
14187
+ default: false
14188
+ },
14184
14189
  watch: {
14185
14190
  type: "boolean",
14186
14191
  alias: "w",
@@ -14360,6 +14365,9 @@ var scanCommand = defineCommand2({
14360
14365
  const reportPath = generateReport(reportDir, score, git, agents, tests, args.since, sdlcAnalysis, scanCost, analysis);
14361
14366
  console.log(` ${icons.success} Report saved: ${colors2.dim(reportPath)}`);
14362
14367
  }
14368
+ if (!args["no-recommend"]) {
14369
+ await showQuickRecommendations(analysis, agents, tests, projectDir);
14370
+ }
14363
14371
  }
14364
14372
  if (args.offline) {
14365
14373
  if (!silent) {
@@ -14656,6 +14664,67 @@ function formatTokensPlain(tokens) {
14656
14664
  return `${Math.round(tokens / 1000)}K`;
14657
14665
  return tokens.toString();
14658
14666
  }
14667
+ async function showQuickRecommendations(analysis, agents, tests, projectDir) {
14668
+ const suggestions = [];
14669
+ if (analysis.sessionPatterns.memoryLossCount > 2 || analysis.sessionPatterns.contextCompactions > 3) {
14670
+ suggestions.push({
14671
+ icon: "\uD83E\uDDE0",
14672
+ text: "Frequent context loss detected",
14673
+ tool: "Supermemory"
14674
+ });
14675
+ }
14676
+ if (!analysis.environment.hasContext7 && analysis.sessionPatterns.toolFailures > 2) {
14677
+ suggestions.push({
14678
+ icon: "\uD83D\uDCDA",
14679
+ text: "API hallucinations likely",
14680
+ tool: "Context7"
14681
+ });
14682
+ }
14683
+ if (!tests || tests.totalTests === 0) {
14684
+ suggestions.push({
14685
+ icon: "\uD83E\uDDEA",
14686
+ text: "No tests detected",
14687
+ tool: "Agentic TDD workflow"
14688
+ });
14689
+ }
14690
+ if (analysis.sessionPatterns.longBackForth > 2) {
14691
+ suggestions.push({
14692
+ icon: "\uD83D\uDCAC",
14693
+ text: "Excessive back-and-forth in sessions",
14694
+ tool: "Skills/structured prompts"
14695
+ });
14696
+ }
14697
+ if (!analysis.environment.hasBeads && agents && agents.totalSessions > 5) {
14698
+ suggestions.push({
14699
+ icon: "\uD83D\uDCCB",
14700
+ text: "No persistent task tracking",
14701
+ tool: "Beads"
14702
+ });
14703
+ }
14704
+ if (analysis.efficiency.tokensWastedWeekly > 50000) {
14705
+ suggestions.push({
14706
+ icon: "\uD83D\uDCB0",
14707
+ text: `~${formatTokensPlain(analysis.efficiency.tokensWastedWeekly)} tokens wasted/week`,
14708
+ tool: "Token optimization"
14709
+ });
14710
+ }
14711
+ if (suggestions.length === 0) {
14712
+ return;
14713
+ }
14714
+ const toShow = suggestions.slice(0, 3);
14715
+ console.log();
14716
+ console.log(` ${colors2.bold(colors2.primary("Quick Recommendations"))}`);
14717
+ console.log(colors2.dim(" " + "─".repeat(40)));
14718
+ console.log();
14719
+ for (const suggestion of toShow) {
14720
+ const toolHint = suggestion.tool ? colors2.success(` → ${suggestion.tool}`) : "";
14721
+ console.log(` ${suggestion.icon} ${suggestion.text}${toolHint}`);
14722
+ await sleep(100);
14723
+ }
14724
+ console.log();
14725
+ console.log(` ${colors2.dim(`Run ${colors2.primary("nb recommend")} for personalized tool suggestions`)}`);
14726
+ console.log(` ${colors2.dim(`Use ${colors2.primary("nb scan --no-recommend")} to skip this`)}`);
14727
+ }
14659
14728
 
14660
14729
  // src/commands/report.ts
14661
14730
  init_dist();
@@ -23629,10 +23698,937 @@ var setupCommand = defineCommand2({
23629
23698
  }
23630
23699
  }
23631
23700
  });
23701
+
23702
+ // src/commands/onboard.ts
23703
+ init_dist();
23704
+ init_client();
23705
+ import { existsSync as existsSync15, mkdirSync as mkdirSync5, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "node:fs";
23706
+ import { join as join15, basename as basename5 } from "node:path";
23707
+ var TECH_PATTERNS = {
23708
+ typescript: ["tsconfig.json", "*.ts", "*.tsx"],
23709
+ javascript: ["*.js", "*.jsx", "*.mjs"],
23710
+ python: ["*.py", "requirements.txt", "pyproject.toml", "setup.py"],
23711
+ rust: ["Cargo.toml", "*.rs"],
23712
+ go: ["go.mod", "*.go"],
23713
+ nextjs: ["next.config.js", "next.config.ts", "next.config.mjs"],
23714
+ react: ["package.json:react"],
23715
+ vue: ["vue.config.js", "nuxt.config.ts", "package.json:vue"],
23716
+ svelte: ["svelte.config.js", "package.json:svelte"],
23717
+ astro: ["astro.config.mjs", "astro.config.ts"],
23718
+ express: ["package.json:express"],
23719
+ fastify: ["package.json:fastify"],
23720
+ hono: ["package.json:hono"],
23721
+ django: ["manage.py", "settings.py"],
23722
+ flask: ["app.py:Flask"],
23723
+ prisma: ["prisma/schema.prisma"],
23724
+ drizzle: ["drizzle.config.ts"],
23725
+ convex: ["convex/"],
23726
+ supabase: [".supabase/", "supabase/"],
23727
+ vitest: ["vitest.config.ts", "vitest.config.js"],
23728
+ jest: ["jest.config.ts", "jest.config.js"],
23729
+ playwright: ["playwright.config.ts"],
23730
+ langchain: ["package.json:langchain", "requirements.txt:langchain"],
23731
+ openai: ["package.json:openai", "requirements.txt:openai"],
23732
+ anthropic: ["package.json:@anthropic-ai"]
23733
+ };
23734
+ var PROJECT_TYPES = {
23735
+ "Web App": ["nextjs", "react", "vue", "svelte", "astro"],
23736
+ "API/Backend": ["express", "fastify", "hono", "django", "flask"],
23737
+ "CLI Tool": ["citty", "commander", "yargs"],
23738
+ Library: ["tsup", "rollup", "esbuild"],
23739
+ "Mobile App": ["react-native", "expo"],
23740
+ "AI/ML": ["langchain", "openai", "anthropic"]
23741
+ };
23742
+ var onboardCommand = defineCommand2({
23743
+ meta: {
23744
+ name: "onboard",
23745
+ description: "Set up project context for personalized AI workflow recommendations"
23746
+ },
23747
+ args: {
23748
+ force: {
23749
+ type: "boolean",
23750
+ description: "Re-run onboarding even if already configured",
23751
+ default: false
23752
+ }
23753
+ },
23754
+ async run({ args }) {
23755
+ const projectPath = process.cwd();
23756
+ const contextPath = join15(projectPath, ".nairon", "context.json");
23757
+ if (existsSync15(contextPath) && !args.force) {
23758
+ const existing = JSON.parse(readFileSync12(contextPath, "utf-8"));
23759
+ consola.info("Project already onboarded. Use --force to re-run.");
23760
+ consola.info(`Business: ${existing.businessContext?.slice(0, 50)}...`);
23761
+ consola.info(`Stack: ${existing.techStack?.join(", ")}`);
23762
+ return;
23763
+ }
23764
+ consola.log("");
23765
+ consola.box({
23766
+ title: "Project Onboarding",
23767
+ message: [
23768
+ "Let's set up your project context for personalized recommendations.",
23769
+ "",
23770
+ "This helps Nairon Bench suggest tools and workflows",
23771
+ "that are specifically relevant to YOUR project."
23772
+ ].join(`
23773
+ `)
23774
+ });
23775
+ consola.log("");
23776
+ consola.start("Step 1/4: Detecting tech stack...");
23777
+ const { techStack, languages } = detectTechStack(projectPath);
23778
+ const projectType = detectProjectType(techStack);
23779
+ consola.success(`Detected: ${techStack.slice(0, 5).join(", ")}${techStack.length > 5 ? ` +${techStack.length - 5} more` : ""}`);
23780
+ consola.info(`Project type: ${projectType}`);
23781
+ const confirmStack = await consola.prompt("Is this correct?", {
23782
+ type: "confirm",
23783
+ initial: true
23784
+ });
23785
+ let finalStack = techStack;
23786
+ if (confirmStack === false) {
23787
+ const stackInput = await consola.prompt("Enter your tech stack (comma-separated):", {
23788
+ type: "text",
23789
+ default: techStack.join(", ")
23790
+ });
23791
+ if (typeof stackInput === "string") {
23792
+ finalStack = stackInput.split(",").map((s2) => s2.trim()).filter(Boolean);
23793
+ }
23794
+ }
23795
+ consola.log("");
23796
+ consola.info("Step 2/4: Tell us about your project");
23797
+ const businessContext = await consola.prompt("What are you building? (e.g., 'B2B SaaS for invoice automation', 'Personal blog with AI features')", {
23798
+ type: "text",
23799
+ placeholder: "Describe your project in 1-2 sentences"
23800
+ });
23801
+ if (typeof businessContext === "symbol" || !businessContext) {
23802
+ consola.warn("Onboarding cancelled.");
23803
+ return;
23804
+ }
23805
+ const targetUsers = await consola.prompt("Who are your target users? (e.g., 'SMB accountants', 'Developers', 'General consumers')", {
23806
+ type: "text",
23807
+ placeholder: "Describe your target audience"
23808
+ });
23809
+ if (typeof targetUsers === "symbol" || !targetUsers) {
23810
+ consola.warn("Onboarding cancelled.");
23811
+ return;
23812
+ }
23813
+ consola.log("");
23814
+ consola.info("Step 3/4: What are your biggest workflow challenges?");
23815
+ const painPointOptions = [
23816
+ { label: "Finding the right context/docs for AI", value: "context" },
23817
+ { label: "Long sessions that lose context", value: "session_length" },
23818
+ { label: "AI hallucinations / wrong code", value: "hallucinations" },
23819
+ { label: "Testing and debugging AI-generated code", value: "testing" },
23820
+ { label: "Prompt engineering / getting good outputs", value: "prompting" },
23821
+ { label: "Managing multiple AI tools", value: "tool_management" },
23822
+ { label: "Cost management / token efficiency", value: "cost" }
23823
+ ];
23824
+ const selectedPainPoints = await consola.prompt("Select your top challenges:", {
23825
+ type: "multiselect",
23826
+ options: painPointOptions
23827
+ });
23828
+ const painPoints = Array.isArray(selectedPainPoints) ? selectedPainPoints.map((p) => typeof p === "string" ? p : p.value) : [];
23829
+ consola.log("");
23830
+ consola.start("Step 4/4: Detecting installed AI tools...");
23831
+ const installedTools = detectInstalledTools(projectPath);
23832
+ consola.success(`Found: ${installedTools.length > 0 ? installedTools.join(", ") : "None detected"}`);
23833
+ const context = {
23834
+ projectPath,
23835
+ projectName: basename5(projectPath),
23836
+ businessContext,
23837
+ targetUsers,
23838
+ techStack: finalStack,
23839
+ detectedLanguages: languages,
23840
+ painPoints,
23841
+ installedTools,
23842
+ primaryAgent: detectPrimaryAgent(),
23843
+ createdAt: new Date().toISOString(),
23844
+ updatedAt: new Date().toISOString()
23845
+ };
23846
+ const naironDir = join15(projectPath, ".nairon");
23847
+ if (!existsSync15(naironDir)) {
23848
+ mkdirSync5(naironDir, { recursive: true });
23849
+ }
23850
+ writeFileSync7(contextPath, JSON.stringify(context, null, 2));
23851
+ consola.success(`Saved to ${contextPath}`);
23852
+ const client = getClient();
23853
+ const config = getConfig();
23854
+ if (client) {
23855
+ consola.start("Syncing to cloud...");
23856
+ try {
23857
+ await client.mutation(api.nightcrawler.saveProjectContext, {
23858
+ projectPath,
23859
+ businessContext: context.businessContext,
23860
+ targetUsers: context.targetUsers,
23861
+ techStack: context.techStack,
23862
+ detectedLanguages: context.detectedLanguages,
23863
+ painPoints: context.painPoints,
23864
+ installedTools: context.installedTools,
23865
+ ...context.primaryAgent ? { primaryAgent: context.primaryAgent } : {}
23866
+ });
23867
+ consola.success("Project context synced to cloud");
23868
+ } catch (err) {
23869
+ consola.warn(`Cloud sync failed: ${err instanceof Error ? err.message : String(err)}`);
23870
+ }
23871
+ }
23872
+ const recommendations = getQuickRecommendations(context);
23873
+ consola.log("");
23874
+ consola.box({
23875
+ title: "Onboarding Complete!",
23876
+ message: [
23877
+ `Project: ${context.projectName}`,
23878
+ `Type: ${projectType}`,
23879
+ `Stack: ${finalStack.slice(0, 4).join(", ")}`,
23880
+ `Pain points: ${painPoints.length} identified`,
23881
+ "",
23882
+ "Quick recommendations based on your profile:",
23883
+ ...recommendations.map((r3) => ` ${r3.icon} ${r3.title}`),
23884
+ "",
23885
+ "Run 'nb recommend' for detailed suggestions",
23886
+ "Run 'nb trending' to see what's hot in the community"
23887
+ ].join(`
23888
+ `)
23889
+ });
23890
+ }
23891
+ });
23892
+ function detectTechStack(projectPath) {
23893
+ const techStack = [];
23894
+ const languages = [];
23895
+ const pkgPath = join15(projectPath, "package.json");
23896
+ let pkgJson = {};
23897
+ if (existsSync15(pkgPath)) {
23898
+ try {
23899
+ pkgJson = JSON.parse(readFileSync12(pkgPath, "utf-8"));
23900
+ } catch {}
23901
+ }
23902
+ const allDeps = {
23903
+ ...pkgJson.dependencies,
23904
+ ...pkgJson.devDependencies
23905
+ };
23906
+ for (const [tech, patterns] of Object.entries(TECH_PATTERNS)) {
23907
+ for (const pattern of patterns) {
23908
+ if (pattern.startsWith("package.json:")) {
23909
+ const dep = pattern.replace("package.json:", "");
23910
+ if (allDeps[dep]) {
23911
+ techStack.push(tech);
23912
+ break;
23913
+ }
23914
+ } else if (pattern.includes("/")) {
23915
+ if (existsSync15(join15(projectPath, pattern))) {
23916
+ techStack.push(tech);
23917
+ break;
23918
+ }
23919
+ } else if (!pattern.includes("*")) {
23920
+ if (existsSync15(join15(projectPath, pattern))) {
23921
+ techStack.push(tech);
23922
+ break;
23923
+ }
23924
+ }
23925
+ }
23926
+ }
23927
+ if (techStack.includes("typescript") || existsSync15(join15(projectPath, "tsconfig.json"))) {
23928
+ languages.push("TypeScript");
23929
+ }
23930
+ if (techStack.includes("javascript") || pkgJson.name) {
23931
+ languages.push("JavaScript");
23932
+ }
23933
+ if (techStack.includes("python") || existsSync15(join15(projectPath, "requirements.txt"))) {
23934
+ languages.push("Python");
23935
+ }
23936
+ if (techStack.includes("rust"))
23937
+ languages.push("Rust");
23938
+ if (techStack.includes("go"))
23939
+ languages.push("Go");
23940
+ return { techStack, languages };
23941
+ }
23942
+ function detectProjectType(techStack) {
23943
+ for (const [type, techs] of Object.entries(PROJECT_TYPES)) {
23944
+ if (techs.some((t2) => techStack.includes(t2))) {
23945
+ return type;
23946
+ }
23947
+ }
23948
+ return "General";
23949
+ }
23950
+ function detectInstalledTools(projectPath) {
23951
+ const tools = [];
23952
+ const home = process.env.HOME || "";
23953
+ const claudeConfigPath = join15(home, ".claude", "claude_desktop_config.json");
23954
+ if (existsSync15(claudeConfigPath)) {
23955
+ try {
23956
+ const config = JSON.parse(readFileSync12(claudeConfigPath, "utf-8"));
23957
+ if (config.mcpServers) {
23958
+ tools.push(...Object.keys(config.mcpServers));
23959
+ }
23960
+ } catch {}
23961
+ }
23962
+ const projectClaudeConfig = join15(projectPath, ".claude", "settings.json");
23963
+ if (existsSync15(projectClaudeConfig)) {
23964
+ try {
23965
+ const config = JSON.parse(readFileSync12(projectClaudeConfig, "utf-8"));
23966
+ if (config.mcpServers) {
23967
+ tools.push(...Object.keys(config.mcpServers));
23968
+ }
23969
+ } catch {}
23970
+ }
23971
+ const skillsDir = join15(home, ".claude", "skills");
23972
+ if (existsSync15(skillsDir)) {
23973
+ try {
23974
+ const { readdirSync: readdirSync8 } = __require("fs");
23975
+ const skills = readdirSync8(skillsDir);
23976
+ tools.push(...skills.filter((s2) => !s2.startsWith(".")));
23977
+ } catch {}
23978
+ }
23979
+ return [...new Set(tools)];
23980
+ }
23981
+ function detectPrimaryAgent() {
23982
+ const home = process.env.HOME || "";
23983
+ if (existsSync15(join15(home, ".claude")))
23984
+ return "claude-code";
23985
+ if (existsSync15(join15(home, ".cursor")))
23986
+ return "cursor";
23987
+ if (existsSync15(join15(home, ".config", "opencode")))
23988
+ return "opencode";
23989
+ return;
23990
+ }
23991
+ function getQuickRecommendations(context) {
23992
+ const recs = [];
23993
+ if (context.painPoints.includes("context") && !context.installedTools.includes("context7")) {
23994
+ recs.push({ icon: "\uD83D\uDCDA", title: "Context7 MCP - Better library docs in context" });
23995
+ }
23996
+ if (context.painPoints.includes("session_length") && !context.installedTools.includes("supermemory")) {
23997
+ recs.push({ icon: "\uD83E\uDDE0", title: "Supermemory - Persistent memory across sessions" });
23998
+ }
23999
+ if (context.painPoints.includes("testing")) {
24000
+ recs.push({ icon: "\uD83E\uDDEA", title: "Agentic TDD workflow - AI-assisted test-driven dev" });
24001
+ }
24002
+ if (context.painPoints.includes("cost")) {
24003
+ recs.push({ icon: "\uD83D\uDCB0", title: "OpenRouter - Route to cheapest model per task" });
24004
+ }
24005
+ if (context.painPoints.includes("prompting")) {
24006
+ recs.push({ icon: "✨", title: "Structured prompting patterns from community" });
24007
+ }
24008
+ if (recs.length === 0) {
24009
+ recs.push({ icon: "\uD83D\uDD25", title: "Run 'nb trending' to see what's hot" });
24010
+ }
24011
+ return recs.slice(0, 3);
24012
+ }
24013
+
24014
+ // src/commands/trending.ts
24015
+ init_dist();
24016
+ init_client();
24017
+ var CYAN = "\x1B[36m";
24018
+ var YELLOW = "\x1B[33m";
24019
+ var GREEN = "\x1B[32m";
24020
+ var DIM = "\x1B[2m";
24021
+ var BOLD = "\x1B[1m";
24022
+ var RESET = "\x1B[0m";
24023
+ var MAGENTA = "\x1B[35m";
24024
+ var CATEGORY_ICONS = {
24025
+ announcement: "\uD83D\uDCE2",
24026
+ launch: "\uD83D\uDE80",
24027
+ usage_pattern: "\uD83D\uDCA1",
24028
+ tutorial: "\uD83D\uDCFA",
24029
+ tip: "⚡"
24030
+ };
24031
+ var CATEGORY_LABELS = {
24032
+ announcement: "ANNOUNCEMENTS",
24033
+ launch: "LAUNCHES",
24034
+ usage_pattern: "WORKFLOWS",
24035
+ tutorial: "TUTORIALS",
24036
+ tip: "TIPS"
24037
+ };
24038
+ var trendingCommand = defineCommand2({
24039
+ meta: {
24040
+ name: "trending",
24041
+ description: "See what's hot in the AI dev tools community"
24042
+ },
24043
+ args: {
24044
+ days: {
24045
+ type: "string",
24046
+ description: "Time range (1, 7, 30)",
24047
+ default: "7"
24048
+ },
24049
+ category: {
24050
+ type: "string",
24051
+ description: "Filter by category (announcement, launch, usage_pattern, tutorial, tip)"
24052
+ },
24053
+ limit: {
24054
+ type: "string",
24055
+ description: "Max results per category",
24056
+ default: "5"
24057
+ },
24058
+ tools: {
24059
+ type: "boolean",
24060
+ description: "Show top tools only",
24061
+ default: false
24062
+ }
24063
+ },
24064
+ async run({ args }) {
24065
+ const client = getClient();
24066
+ if (!client) {
24067
+ consola.error("Not connected to cloud. Run 'nb doctor' to check connection.");
24068
+ return;
24069
+ }
24070
+ const days = parseInt(args.days) || 7;
24071
+ const limit = parseInt(args.limit) || 5;
24072
+ consola.log("");
24073
+ console.log(`${YELLOW}\uD83D\uDD25 Hot Topics — Last ${days} Day${days > 1 ? "s" : ""}${RESET}`);
24074
+ console.log(`${DIM}${"─".repeat(50)}${RESET}`);
24075
+ try {
24076
+ if (args.tools) {
24077
+ await showTopTools(client, days, limit * 2);
24078
+ return;
24079
+ }
24080
+ const insights = await client.query(api.nightcrawler.getRecentInsights, {
24081
+ limit: 50,
24082
+ maxHypeScore: 70,
24083
+ ...args.category ? { category: args.category } : {}
24084
+ });
24085
+ if (insights.length === 0) {
24086
+ consola.log("");
24087
+ consola.warn("No trending insights found. The Nightcrawler may not have run yet.");
24088
+ consola.info("Run the Nightcrawler manually or wait for the scheduled job.");
24089
+ showFallbackMessage();
24090
+ return;
24091
+ }
24092
+ const byCategory = {};
24093
+ for (const insight of insights) {
24094
+ const cat = insight.category;
24095
+ if (!byCategory[cat]) {
24096
+ byCategory[cat] = [];
24097
+ }
24098
+ byCategory[cat].push(insight);
24099
+ }
24100
+ const categoryOrder = ["announcement", "launch", "usage_pattern", "tutorial", "tip"];
24101
+ for (const category of categoryOrder) {
24102
+ const categoryInsights = byCategory[category];
24103
+ if (!categoryInsights || categoryInsights.length === 0)
24104
+ continue;
24105
+ const icon = CATEGORY_ICONS[category] || "\uD83D\uDCCC";
24106
+ const label = CATEGORY_LABELS[category] || category.toUpperCase();
24107
+ consola.log("");
24108
+ console.log(`${BOLD}${icon} ${label}${RESET}`);
24109
+ for (const insight of categoryInsights.slice(0, limit)) {
24110
+ const likes = formatNumber2(insight.engagement.likes);
24111
+ const hasVideo = insight.hasVideo ? `${MAGENTA}▶${RESET} ` : "";
24112
+ const tools = insight.toolsMentioned.length > 0 ? `${DIM}[${insight.toolsMentioned.slice(0, 2).join(", ")}]${RESET}` : "";
24113
+ console.log(`${DIM}├─${RESET} ${hasVideo}${insight.keyInsight.slice(0, 60)}${insight.keyInsight.length > 60 ? "..." : ""}`);
24114
+ console.log(`${DIM}│ ${RESET}${GREEN}${likes}❤${RESET} @${insight.authorHandle} ${tools}`);
24115
+ }
24116
+ console.log(`${DIM}└─${RESET}`);
24117
+ }
24118
+ consola.log("");
24119
+ await showTopTools(client, days, 5);
24120
+ consola.log("");
24121
+ console.log(`${DIM}Run 'nb trending --tools' for detailed tool rankings${RESET}`);
24122
+ console.log(`${DIM}Run 'nb recommend' for personalized suggestions${RESET}`);
24123
+ } catch (err) {
24124
+ consola.error(`Failed to fetch trending: ${err instanceof Error ? err.message : String(err)}`);
24125
+ showFallbackMessage();
24126
+ }
24127
+ }
24128
+ });
24129
+ async function showTopTools(client, days, limit) {
24130
+ try {
24131
+ const trending = await client.query(api.nightcrawler.getTrendingTools, {
24132
+ days,
24133
+ limit
24134
+ });
24135
+ if (trending.length === 0) {
24136
+ console.log(`${DIM}No tool data available yet.${RESET}`);
24137
+ return;
24138
+ }
24139
+ console.log(`${BOLD}\uD83D\uDEE0️ TOP TOOLS${RESET}`);
24140
+ for (let i3 = 0;i3 < trending.length; i3++) {
24141
+ const tool = trending[i3];
24142
+ const rank = i3 + 1;
24143
+ const bar = createBar(tool.mentions, trending[0].mentions);
24144
+ const avgLikes = formatNumber2(tool.avgLikes);
24145
+ console.log(`${DIM}${rank}.${RESET} ${CYAN}${tool.tool}${RESET}`);
24146
+ console.log(` ${bar} ${tool.mentions} mentions · ${avgLikes} avg❤`);
24147
+ }
24148
+ } catch (err) {
24149
+ console.log(`${DIM}Could not fetch tool rankings.${RESET}`);
24150
+ }
24151
+ }
24152
+ function showFallbackMessage() {
24153
+ consola.log("");
24154
+ consola.box({
24155
+ title: "Nightcrawler Not Running",
24156
+ message: [
24157
+ "The trending data comes from the Nightcrawler background job",
24158
+ "which scrapes X/Twitter for high-engagement dev tool posts.",
24159
+ "",
24160
+ "To populate data manually, run:",
24161
+ " cd skills/x-research",
24162
+ ' bun run x-search.ts search "MCP server" --quick',
24163
+ "",
24164
+ "Or wait for the scheduled Nightcrawler job."
24165
+ ].join(`
24166
+ `)
24167
+ });
24168
+ }
24169
+ function formatNumber2(num) {
24170
+ if (num >= 1e6)
24171
+ return `${(num / 1e6).toFixed(1)}M`;
24172
+ if (num >= 1000)
24173
+ return `${(num / 1000).toFixed(1)}K`;
24174
+ return num.toString();
24175
+ }
24176
+ function createBar(value, max, width = 15) {
24177
+ const filled = Math.round(value / max * width);
24178
+ const empty = width - filled;
24179
+ return `${GREEN}${"█".repeat(filled)}${RESET}${DIM}${"░".repeat(empty)}${RESET}`;
24180
+ }
24181
+
24182
+ // src/commands/recommend.ts
24183
+ init_dist();
24184
+ init_client();
24185
+ import { existsSync as existsSync16, readFileSync as readFileSync13 } from "node:fs";
24186
+ import { join as join16 } from "node:path";
24187
+ var CYAN2 = "\x1B[36m";
24188
+ var YELLOW2 = "\x1B[33m";
24189
+ var GREEN2 = "\x1B[32m";
24190
+ var DIM2 = "\x1B[2m";
24191
+ var BOLD2 = "\x1B[1m";
24192
+ var RESET2 = "\x1B[0m";
24193
+ var MAGENTA2 = "\x1B[35m";
24194
+ var PAIN_POINT_TOOLS = {
24195
+ context: [
24196
+ { tool: "context7", reason: "Fetches up-to-date library docs directly into AI context", installCmd: "nb tools install context7" },
24197
+ { tool: "nia", reason: "Index and search external repos, docs, and packages" }
24198
+ ],
24199
+ session_length: [
24200
+ { tool: "supermemory", reason: "Persistent memory across sessions - never lose context", installCmd: "nb tools install supermemory" },
24201
+ { tool: "beads", reason: "Task tracking that persists between sessions" }
24202
+ ],
24203
+ hallucinations: [
24204
+ { tool: "context7", reason: "Real docs reduce hallucinations by 40%+", installCmd: "nb tools install context7" },
24205
+ { tool: "repoprompt", reason: "Better context building for accurate code generation" }
24206
+ ],
24207
+ testing: [
24208
+ { tool: "stagehand", reason: "AI-powered E2E testing with Playwright" },
24209
+ { tool: "agentic-tdd", reason: "Test-driven development workflow for AI coding" }
24210
+ ],
24211
+ prompting: [
24212
+ { tool: "skills", reason: "Pre-built prompt patterns for common tasks" },
24213
+ { tool: "structured-prompts", reason: "Templates that get better AI outputs" }
24214
+ ],
24215
+ tool_management: [
24216
+ { tool: "oh-my-opencode", reason: "Unified agent harness - one config for all tools" },
24217
+ { tool: "mcp-installer", reason: "Easy MCP server management" }
24218
+ ],
24219
+ cost: [
24220
+ { tool: "openrouter", reason: "Route to cheapest model per task", installCmd: "nb tools install openrouter" },
24221
+ { tool: "token-counter", reason: "Track and optimize token usage" }
24222
+ ]
24223
+ };
24224
+ var STACK_TOOLS = {
24225
+ nextjs: [{ tool: "vercel-mcp", reason: "Deploy and manage Vercel projects from AI" }],
24226
+ react: [{ tool: "storybook-mcp", reason: "AI-assisted component development" }],
24227
+ typescript: [{ tool: "typescript-mcp", reason: "Better type inference in AI context" }],
24228
+ prisma: [{ tool: "prisma-mcp", reason: "Database schema and queries in AI context" }],
24229
+ convex: [{ tool: "convex-mcp", reason: "Convex functions and schema in AI context" }],
24230
+ python: [{ tool: "python-mcp", reason: "Python environment and packages in AI context" }]
24231
+ };
24232
+ var recommendCommand = defineCommand2({
24233
+ meta: {
24234
+ name: "recommend",
24235
+ description: "Get personalized AI workflow recommendations based on your project"
24236
+ },
24237
+ args: {
24238
+ scan: {
24239
+ type: "boolean",
24240
+ description: "Re-analyze project before recommending",
24241
+ default: false
24242
+ },
24243
+ limit: {
24244
+ type: "string",
24245
+ description: "Max recommendations to show",
24246
+ default: "5"
24247
+ },
24248
+ all: {
24249
+ type: "boolean",
24250
+ description: "Show all recommendations (not just top)",
24251
+ default: false
24252
+ }
24253
+ },
24254
+ async run({ args }) {
24255
+ const projectPath = process.cwd();
24256
+ const contextPath = join16(projectPath, ".nairon", "context.json");
24257
+ const limit = parseInt(args.limit) || 5;
24258
+ consola.log("");
24259
+ console.log(`${YELLOW2}\uD83D\uDCCA Analyzing your project...${RESET2}`);
24260
+ let context = null;
24261
+ if (existsSync16(contextPath)) {
24262
+ try {
24263
+ context = JSON.parse(readFileSync13(contextPath, "utf-8"));
24264
+ console.log(`${DIM2}Loaded context from ${contextPath}${RESET2}`);
24265
+ } catch {}
24266
+ }
24267
+ if (!context) {
24268
+ consola.warn("No project context found. Run 'nb onboard' first for personalized recommendations.");
24269
+ consola.log("");
24270
+ await showGenericRecommendations();
24271
+ return;
24272
+ }
24273
+ const recommendations = [];
24274
+ for (const painPoint of context.painPoints) {
24275
+ const tools = PAIN_POINT_TOOLS[painPoint] || [];
24276
+ for (const tool of tools) {
24277
+ if (!context.installedTools.includes(tool.tool)) {
24278
+ recommendations.push({
24279
+ tool: tool.tool,
24280
+ reason: tool.reason,
24281
+ source: "pain_point",
24282
+ relevanceScore: 0.9,
24283
+ installCmd: tool.installCmd
24284
+ });
24285
+ }
24286
+ }
24287
+ }
24288
+ for (const tech of context.techStack) {
24289
+ const tools = STACK_TOOLS[tech.toLowerCase()] || [];
24290
+ for (const tool of tools) {
24291
+ if (!context.installedTools.includes(tool.tool)) {
24292
+ recommendations.push({
24293
+ tool: tool.tool,
24294
+ reason: tool.reason,
24295
+ source: "stack",
24296
+ relevanceScore: 0.7
24297
+ });
24298
+ }
24299
+ }
24300
+ }
24301
+ const client = getClient();
24302
+ if (client) {
24303
+ try {
24304
+ const trending = await client.query(api.nightcrawler.getRecommendationsForProject, {
24305
+ projectPath,
24306
+ limit: 10
24307
+ });
24308
+ for (const t2 of trending) {
24309
+ if (recommendations.some((r3) => r3.tool === t2.toolSlug))
24310
+ continue;
24311
+ if (context.installedTools.includes(t2.toolSlug))
24312
+ continue;
24313
+ recommendations.push({
24314
+ tool: t2.toolSlug,
24315
+ reason: t2.reason,
24316
+ source: "trending",
24317
+ relevanceScore: t2.relevanceScore,
24318
+ trendingMentions: t2.mentions
24319
+ });
24320
+ }
24321
+ } catch (err) {}
24322
+ }
24323
+ const seen = new Set;
24324
+ const uniqueRecs = recommendations.filter((r3) => {
24325
+ if (seen.has(r3.tool))
24326
+ return false;
24327
+ seen.add(r3.tool);
24328
+ return true;
24329
+ }).sort((a2, b2) => b2.relevanceScore - a2.relevanceScore);
24330
+ consola.log("");
24331
+ console.log(`${BOLD2}${CYAN2}RECOMMENDATIONS FOR ${context.projectName.toUpperCase()}${RESET2}`);
24332
+ console.log(`${DIM2}Based on: ${context.painPoints.length} pain points, ${context.techStack.length} stack items${RESET2}`);
24333
+ console.log(`${DIM2}${"─".repeat(50)}${RESET2}`);
24334
+ const toShow = args.all ? uniqueRecs : uniqueRecs.slice(0, limit);
24335
+ if (toShow.length === 0) {
24336
+ consola.success("Your setup looks great! No new recommendations at this time.");
24337
+ consola.log("");
24338
+ console.log(`${DIM2}Run 'nb trending' to see what's new in the community${RESET2}`);
24339
+ return;
24340
+ }
24341
+ for (let i3 = 0;i3 < toShow.length; i3++) {
24342
+ const rec = toShow[i3];
24343
+ const num = i3 + 1;
24344
+ const sourceIcon = getSourceIcon(rec.source);
24345
+ const trendingBadge = rec.trendingMentions ? `${MAGENTA2}↑${rec.trendingMentions}${RESET2} ` : "";
24346
+ consola.log("");
24347
+ console.log(`${BOLD2}${num}. ${CYAN2}${rec.tool}${RESET2} ${sourceIcon}`);
24348
+ console.log(` ${trendingBadge}${rec.reason}`);
24349
+ if (rec.installCmd) {
24350
+ console.log(` ${DIM2}Install: ${GREEN2}${rec.installCmd}${RESET2}`);
24351
+ }
24352
+ }
24353
+ consola.log("");
24354
+ console.log(`${DIM2}${"─".repeat(50)}${RESET2}`);
24355
+ const painPointRecs = toShow.filter((r3) => r3.source === "pain_point").length;
24356
+ const stackRecs = toShow.filter((r3) => r3.source === "stack").length;
24357
+ const trendingRecs = toShow.filter((r3) => r3.source === "trending").length;
24358
+ console.log(`${DIM2}${painPointRecs} for pain points · ${stackRecs} for your stack · ${trendingRecs} trending${RESET2}`);
24359
+ if (!args.all && uniqueRecs.length > limit) {
24360
+ console.log(`${DIM2}Run 'nb recommend --all' to see ${uniqueRecs.length - limit} more${RESET2}`);
24361
+ }
24362
+ if (context.installedTools.length > 0) {
24363
+ consola.log("");
24364
+ console.log(`${GREEN2}✓ Already installed:${RESET2} ${context.installedTools.slice(0, 5).join(", ")}${context.installedTools.length > 5 ? ` +${context.installedTools.length - 5} more` : ""}`);
24365
+ }
24366
+ }
24367
+ });
24368
+ async function showGenericRecommendations() {
24369
+ console.log(`${BOLD2}${CYAN2}TOP COMMUNITY RECOMMENDATIONS${RESET2}`);
24370
+ console.log(`${DIM2}Run 'nb onboard' for personalized suggestions${RESET2}`);
24371
+ console.log(`${DIM2}${"─".repeat(50)}${RESET2}`);
24372
+ consola.log("");
24373
+ const genericRecs = [
24374
+ { tool: "context7", reason: "Up-to-date library docs in AI context - reduces hallucinations" },
24375
+ { tool: "supermemory", reason: "Persistent memory across sessions" },
24376
+ { tool: "repoprompt", reason: "Better context building for code generation" },
24377
+ { tool: "beads", reason: "Task tracking that persists between sessions" },
24378
+ { tool: "stagehand", reason: "AI-powered E2E testing" }
24379
+ ];
24380
+ for (let i3 = 0;i3 < genericRecs.length; i3++) {
24381
+ const rec = genericRecs[i3];
24382
+ console.log(`${BOLD2}${i3 + 1}. ${CYAN2}${rec.tool}${RESET2}`);
24383
+ console.log(` ${rec.reason}`);
24384
+ consola.log("");
24385
+ }
24386
+ }
24387
+ function getSourceIcon(source) {
24388
+ switch (source) {
24389
+ case "pain_point":
24390
+ return `${YELLOW2}[pain point]${RESET2}`;
24391
+ case "stack":
24392
+ return `${GREEN2}[your stack]${RESET2}`;
24393
+ case "trending":
24394
+ return `${MAGENTA2}[trending]${RESET2}`;
24395
+ case "community":
24396
+ return `${DIM2}[community]${RESET2}`;
24397
+ default:
24398
+ return "";
24399
+ }
24400
+ }
24401
+
24402
+ // src/commands/upgrade.ts
24403
+ import { execSync as execSync5 } from "node:child_process";
24404
+ var CYAN3 = "\x1B[36m";
24405
+ var GREEN3 = "\x1B[32m";
24406
+ var YELLOW3 = "\x1B[33m";
24407
+ var DIM3 = "\x1B[2m";
24408
+ var BOLD3 = "\x1B[1m";
24409
+ var RESET3 = "\x1B[0m";
24410
+ var MAGENTA3 = "\x1B[35m";
24411
+ var CHANGELOG = [
24412
+ {
24413
+ version: "0.1.0",
24414
+ date: "2026-02-13",
24415
+ title: "Nightcrawler & Recommendations",
24416
+ highlights: [
24417
+ "nb onboard - Set up project context for personalized recommendations",
24418
+ "nb trending - See hot topics in AI dev tools community",
24419
+ "nb recommend - Get personalized tool suggestions",
24420
+ "Auto-recommendations after nb scan",
24421
+ "Background X/Twitter scraper with hype filter",
24422
+ "Cost-optimized scraping (~$35/month)"
24423
+ ]
24424
+ },
24425
+ {
24426
+ version: "0.0.40",
24427
+ date: "2026-02-10",
24428
+ title: "Frustration Detection & Smarter Reports",
24429
+ highlights: [
24430
+ "Detect frustration patterns in AI sessions",
24431
+ "Improved report generation",
24432
+ "Better token waste analysis"
24433
+ ]
24434
+ },
24435
+ {
24436
+ version: "0.0.34",
24437
+ date: "2026-02-08",
24438
+ title: "Accurate Token & Commit Tracking",
24439
+ highlights: [
24440
+ "Fixed token counting accuracy",
24441
+ "Improved commit attribution",
24442
+ "Better session correlation"
24443
+ ]
24444
+ },
24445
+ {
24446
+ version: "0.0.31",
24447
+ date: "2026-02-08",
24448
+ title: "Multi-Agent Support & Report Sharing",
24449
+ highlights: [
24450
+ "Support for multiple AI agents",
24451
+ "Shareable reports with nb publish",
24452
+ "Improved dashboard"
24453
+ ]
24454
+ },
24455
+ {
24456
+ version: "0.0.26",
24457
+ date: "2026-02-07",
24458
+ title: "Hackathon Reports & Publish Links",
24459
+ highlights: [
24460
+ "nb report for hackathon submissions",
24461
+ "Publishable report links",
24462
+ "SDLC phase analysis"
24463
+ ]
24464
+ },
24465
+ {
24466
+ version: "0.0.22",
24467
+ date: "2026-02-07",
24468
+ title: "Multi-Agent & Team Features",
24469
+ highlights: [
24470
+ "Team workflow support",
24471
+ "Multi-agent session tracking",
24472
+ "Improved cost analysis"
24473
+ ]
24474
+ },
24475
+ {
24476
+ version: "0.0.18",
24477
+ date: "2026-02-07",
24478
+ title: "CI/CD & Analytics",
24479
+ highlights: [
24480
+ "CI/CD integration support",
24481
+ "Enhanced analytics dashboard",
24482
+ "Badge system"
24483
+ ]
24484
+ }
24485
+ ];
24486
+ var upgradeCommand = defineCommand2({
24487
+ meta: {
24488
+ name: "upgrade",
24489
+ description: "Upgrade nairon-bench to the latest version and see what's new"
24490
+ },
24491
+ args: {
24492
+ check: {
24493
+ type: "boolean",
24494
+ description: "Only check for updates without installing",
24495
+ default: false
24496
+ },
24497
+ changelog: {
24498
+ type: "boolean",
24499
+ description: "Show full changelog",
24500
+ default: false
24501
+ }
24502
+ },
24503
+ async run({ args }) {
24504
+ const currentVersion = getCurrentVersion();
24505
+ console.log();
24506
+ console.log(`${BOLD3}${CYAN3} nairon-bench upgrade${RESET3}`);
24507
+ console.log(`${DIM3} ${"─".repeat(40)}${RESET3}`);
24508
+ console.log();
24509
+ if (args.changelog) {
24510
+ showFullChangelog();
24511
+ return;
24512
+ }
24513
+ console.log(`${DIM3} Checking for updates...${RESET3}`);
24514
+ let latestVersion;
24515
+ try {
24516
+ latestVersion = execSync5("npm view nairon-bench version", { encoding: "utf-8" }).trim();
24517
+ } catch {
24518
+ console.log(` ${YELLOW3}⚠${RESET3} Could not check npm registry`);
24519
+ console.log(` ${DIM3}Run 'bun upgrade -g nairon-bench' manually${RESET3}`);
24520
+ return;
24521
+ }
24522
+ console.log();
24523
+ console.log(` ${DIM3}Current:${RESET3} ${currentVersion}`);
24524
+ console.log(` ${DIM3}Latest:${RESET3} ${latestVersion}`);
24525
+ console.log();
24526
+ if (compareVersions(currentVersion, latestVersion) >= 0) {
24527
+ console.log(` ${GREEN3}✓${RESET3} You're on the latest version!`);
24528
+ console.log();
24529
+ console.log(` ${DIM3}Run 'nb upgrade --changelog' to see past releases${RESET3}`);
24530
+ return;
24531
+ }
24532
+ const newReleases = getNewReleases(currentVersion, latestVersion);
24533
+ if (newReleases.length > 0) {
24534
+ showWhatsNew(newReleases);
24535
+ }
24536
+ if (args.check) {
24537
+ console.log();
24538
+ console.log(` ${DIM3}Run 'nb upgrade' to install${RESET3}`);
24539
+ return;
24540
+ }
24541
+ console.log();
24542
+ console.log(`${DIM3} ${"─".repeat(40)}${RESET3}`);
24543
+ console.log(` ${CYAN3}↓${RESET3} Upgrading to ${GREEN3}v${latestVersion}${RESET3}...`);
24544
+ console.log();
24545
+ try {
24546
+ try {
24547
+ execSync5("bun upgrade -g nairon-bench", { stdio: "inherit" });
24548
+ } catch {
24549
+ execSync5("npm install -g nairon-bench@latest", { stdio: "inherit" });
24550
+ }
24551
+ console.log();
24552
+ console.log(` ${GREEN3}✓${RESET3} Upgraded to ${GREEN3}v${latestVersion}${RESET3}`);
24553
+ console.log();
24554
+ console.log(` ${DIM3}Run 'nb doctor' to verify installation${RESET3}`);
24555
+ } catch (err) {
24556
+ console.log();
24557
+ console.log(` ${YELLOW3}⚠${RESET3} Upgrade failed`);
24558
+ console.log(` ${DIM3}Try running manually:${RESET3}`);
24559
+ console.log(` ${CYAN3}bun upgrade -g nairon-bench${RESET3}`);
24560
+ console.log(` ${DIM3}or${RESET3}`);
24561
+ console.log(` ${CYAN3}npm install -g nairon-bench@latest${RESET3}`);
24562
+ }
24563
+ }
24564
+ });
24565
+ function getCurrentVersion() {
24566
+ try {
24567
+ const output = execSync5("nb --version 2>/dev/null || nairon-bench --version 2>/dev/null", {
24568
+ encoding: "utf-8",
24569
+ stdio: ["pipe", "pipe", "pipe"]
24570
+ });
24571
+ const match = output.match(/v?(\d+\.\d+\.\d+)/);
24572
+ return match ? match[1] : "0.0.0";
24573
+ } catch {
24574
+ return "0.0.0";
24575
+ }
24576
+ }
24577
+ function compareVersions(a2, b2) {
24578
+ const partsA = a2.split(".").map(Number);
24579
+ const partsB = b2.split(".").map(Number);
24580
+ for (let i3 = 0;i3 < 3; i3++) {
24581
+ const diff = (partsA[i3] || 0) - (partsB[i3] || 0);
24582
+ if (diff !== 0)
24583
+ return diff;
24584
+ }
24585
+ return 0;
24586
+ }
24587
+ function getNewReleases(currentVersion, latestVersion) {
24588
+ return CHANGELOG.filter((entry) => {
24589
+ return compareVersions(entry.version, currentVersion) > 0 && compareVersions(entry.version, latestVersion) <= 0;
24590
+ });
24591
+ }
24592
+ function showWhatsNew(releases) {
24593
+ console.log(` ${BOLD3}${MAGENTA3}What's New${RESET3}`);
24594
+ console.log();
24595
+ for (const release of releases) {
24596
+ const isMajor = release.version.endsWith(".0") && !release.version.startsWith("0.0.");
24597
+ const isMinor = release.version.split(".")[1] !== "0" && release.version.endsWith(".0");
24598
+ const versionColor = isMajor ? GREEN3 : isMinor ? CYAN3 : DIM3;
24599
+ console.log(` ${versionColor}${BOLD3}v${release.version}${RESET3} ${DIM3}(${release.date})${RESET3}`);
24600
+ console.log(` ${release.title}`);
24601
+ console.log();
24602
+ for (const highlight of release.highlights.slice(0, 4)) {
24603
+ console.log(` ${GREEN3}•${RESET3} ${highlight}`);
24604
+ }
24605
+ if (release.highlights.length > 4) {
24606
+ console.log(` ${DIM3}+ ${release.highlights.length - 4} more improvements${RESET3}`);
24607
+ }
24608
+ console.log();
24609
+ }
24610
+ }
24611
+ function showFullChangelog() {
24612
+ console.log(` ${BOLD3}${MAGENTA3}Full Changelog${RESET3}`);
24613
+ console.log();
24614
+ for (const release of CHANGELOG) {
24615
+ console.log(` ${CYAN3}${BOLD3}v${release.version}${RESET3} ${DIM3}(${release.date})${RESET3}`);
24616
+ console.log(` ${release.title}`);
24617
+ console.log();
24618
+ for (const highlight of release.highlights) {
24619
+ console.log(` ${GREEN3}•${RESET3} ${highlight}`);
24620
+ }
24621
+ console.log();
24622
+ console.log(` ${DIM3}${"─".repeat(38)}${RESET3}`);
24623
+ console.log();
24624
+ }
24625
+ console.log(` ${DIM3}See full history at:${RESET3}`);
24626
+ console.log(` ${CYAN3}https://nairon.ai/changelog${RESET3}`);
24627
+ }
23632
24628
  // package.json
23633
24629
  var package_default = {
23634
24630
  name: "nairon-bench",
23635
- version: "0.0.40",
24631
+ version: "0.1.0",
23636
24632
  description: "AI workflow benchmarking CLI",
23637
24633
  type: "module",
23638
24634
  bin: {
@@ -23677,52 +24673,52 @@ var package_default = {
23677
24673
  };
23678
24674
 
23679
24675
  // src/lib/mascot.ts
23680
- var CYAN = "\x1B[36m";
24676
+ var CYAN4 = "\x1B[36m";
23681
24677
  var WHITE = "\x1B[97m";
23682
- var DIM = "\x1B[2m";
23683
- var BOLD = "\x1B[1m";
23684
- var RESET = "\x1B[0m";
24678
+ var DIM4 = "\x1B[2m";
24679
+ var BOLD4 = "\x1B[1m";
24680
+ var RESET4 = "\x1B[0m";
23685
24681
  function renderMascot(version2, cwd) {
23686
24682
  const projectName = cwd ? cwd.split("/").pop() || cwd : "";
23687
- const projectLine = projectName ? ` ${DIM}${projectName}${RESET}` : "";
24683
+ const projectLine = projectName ? ` ${DIM4}${projectName}${RESET4}` : "";
23688
24684
  return `
23689
- ${WHITE} ▗▄▄▄▄▄▄▄▄▖${RESET}
23690
- ${WHITE} ▐${CYAN}█▀▀▀▀▀▀█${WHITE}▌${RESET} ${BOLD}NBench${RESET} ${DIM}v${version2}${RESET}
23691
- ${WHITE} ▐${CYAN}█ ${WHITE}▲${CYAN} █${WHITE}▌${RESET} ${DIM}Benchmark AI workflows${RESET}
23692
- ${WHITE} ▐${CYAN}█▄▄▄▄▄▄█${WHITE}▌${RESET}${projectLine}
23693
- ${WHITE} ▝▀▀▀▀▀▀▀▀▘${RESET}
24685
+ ${WHITE} ▗▄▄▄▄▄▄▄▄▖${RESET4}
24686
+ ${WHITE} ▐${CYAN4}█▀▀▀▀▀▀█${WHITE}▌${RESET4} ${BOLD4}NBench${RESET4} ${DIM4}v${version2}${RESET4}
24687
+ ${WHITE} ▐${CYAN4}█ ${WHITE}▲${CYAN4} █${WHITE}▌${RESET4} ${DIM4}Benchmark AI workflows${RESET4}
24688
+ ${WHITE} ▐${CYAN4}█▄▄▄▄▄▄█${WHITE}▌${RESET4}${projectLine}
24689
+ ${WHITE} ▝▀▀▀▀▀▀▀▀▘${RESET4}
23694
24690
  `;
23695
24691
  }
23696
24692
 
23697
24693
  // src/index.ts
23698
24694
  var VERSION = package_default.version;
23699
- var YELLOW = "\x1B[33m";
23700
- var DIM2 = "\x1B[2m";
23701
- var BOLD2 = "\x1B[1m";
23702
- var RESET2 = "\x1B[0m";
24695
+ var YELLOW4 = "\x1B[33m";
24696
+ var DIM5 = "\x1B[2m";
24697
+ var BOLD5 = "\x1B[1m";
24698
+ var RESET5 = "\x1B[0m";
23703
24699
  function showBanner() {
23704
24700
  const log = (msg) => process.stdout.write(msg + `
23705
24701
  `);
23706
- const GREEN = "\x1B[32m";
23707
- const CYAN2 = "\x1B[36m";
24702
+ const GREEN4 = "\x1B[32m";
24703
+ const CYAN5 = "\x1B[36m";
23708
24704
  log(renderMascot(VERSION, process.cwd()));
23709
- log(`${YELLOW}\u2501\u2501\u2501 Quick Start \u2501\u2501\u2501${RESET2}`);
24705
+ log(`${YELLOW4}\u2501\u2501\u2501 Quick Start \u2501\u2501\u2501${RESET5}`);
23710
24706
  log("");
23711
- log(` ${GREEN}1.${RESET2} ${BOLD2}nb init${RESET2} Set up your profile (first time only)`);
23712
- log(` ${GREEN}2.${RESET2} ${BOLD2}nb scan${RESET2} Analyze your AI coding sessions`);
23713
- log(` ${GREEN}3.${RESET2} ${BOLD2}nb report --publish${RESET2} Generate & share your report`);
24707
+ log(` ${GREEN4}1.${RESET5} ${BOLD5}nb init${RESET5} Set up your profile (first time only)`);
24708
+ log(` ${GREEN4}2.${RESET5} ${BOLD5}nb scan${RESET5} Analyze your AI coding sessions`);
24709
+ log(` ${GREEN4}3.${RESET5} ${BOLD5}nb report --publish${RESET5} Generate & share your report`);
23714
24710
  log("");
23715
- log(`${DIM2}\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510${RESET2}`);
23716
- log(`${DIM2}\u2502${RESET2} ${CYAN2}How often?${RESET2} ${DIM2}\u2502${RESET2}`);
23717
- log(`${DIM2}\u2502${RESET2} \u2022 Run ${BOLD2}nb scan${RESET2} after coding sessions ${DIM2}\u2502${RESET2}`);
23718
- log(`${DIM2}\u2502${RESET2} \u2022 Run ${BOLD2}nb report${RESET2} weekly to track progress ${DIM2}\u2502${RESET2}`);
23719
- log(`${DIM2}\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518${RESET2}`);
24711
+ log(`${DIM5}\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510${RESET5}`);
24712
+ log(`${DIM5}\u2502${RESET5} ${CYAN5}How often?${RESET5} ${DIM5}\u2502${RESET5}`);
24713
+ log(`${DIM5}\u2502${RESET5} \u2022 Run ${BOLD5}nb scan${RESET5} after coding sessions ${DIM5}\u2502${RESET5}`);
24714
+ log(`${DIM5}\u2502${RESET5} \u2022 Run ${BOLD5}nb report${RESET5} weekly to track progress ${DIM5}\u2502${RESET5}`);
24715
+ log(`${DIM5}\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518${RESET5}`);
23720
24716
  log("");
23721
- log(`${DIM2}Run ${BOLD2}nb --help${RESET2}${DIM2} for all commands${RESET2}`);
24717
+ log(`${DIM5}Run ${BOLD5}nb --help${RESET5}${DIM5} for all commands${RESET5}`);
23722
24718
  log("");
23723
24719
  }
23724
24720
  var args = process.argv.slice(2);
23725
- var subcommands = ["init", "scan", "report", "dashboard", "insights", "tools", "doctor", "publish", "history", "cost", "session", "export", "pr", "badges", "cache", "setup"];
24721
+ var subcommands = ["init", "scan", "report", "dashboard", "insights", "tools", "doctor", "publish", "history", "cost", "session", "export", "pr", "badges", "cache", "setup", "onboard", "trending", "recommend"];
23726
24722
  var hasSubcommand = args.some((arg) => subcommands.includes(arg));
23727
24723
  var hasHelp = args.includes("--help") || args.includes("-h");
23728
24724
  var hasVersion = args.includes("--version");
@@ -23751,7 +24747,11 @@ if (!hasSubcommand && !hasHelp && !hasVersion && args.length === 0) {
23751
24747
  pr: prCommand,
23752
24748
  badges: badgesCommand,
23753
24749
  cache: cacheCommand,
23754
- setup: setupCommand
24750
+ setup: setupCommand,
24751
+ onboard: onboardCommand,
24752
+ trending: trendingCommand,
24753
+ recommend: recommendCommand,
24754
+ upgrade: upgradeCommand
23755
24755
  }
23756
24756
  });
23757
24757
  runMain(main);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nairon-bench",
3
- "version": "0.0.40",
3
+ "version": "0.1.0",
4
4
  "description": "AI workflow benchmarking CLI",
5
5
  "type": "module",
6
6
  "bin": {