sverklo 0.26.1 → 0.28.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 (88) hide show
  1. package/dist/bin/sverklo.js +97 -12
  2. package/dist/bin/sverklo.js.map +1 -1
  3. package/dist/src/audit-prompt.js +10 -10
  4. package/dist/src/doctor.js +21 -13
  5. package/dist/src/doctor.js.map +1 -1
  6. package/dist/src/init-global.d.ts +90 -0
  7. package/dist/src/init-global.js +185 -0
  8. package/dist/src/init-global.js.map +1 -0
  9. package/dist/src/init.d.ts +1 -1
  10. package/dist/src/init.js +31 -21
  11. package/dist/src/init.js.map +1 -1
  12. package/dist/src/server/hints.js +40 -41
  13. package/dist/src/server/hints.js.map +1 -1
  14. package/dist/src/server/mcp-server.d.ts +10 -0
  15. package/dist/src/server/mcp-server.js +218 -119
  16. package/dist/src/server/mcp-server.js.map +1 -1
  17. package/dist/src/server/prompts.js +37 -37
  18. package/dist/src/server/prompts.js.map +1 -1
  19. package/dist/src/server/tool-overrides.js +69 -57
  20. package/dist/src/server/tool-overrides.js.map +1 -1
  21. package/dist/src/server/tools/ask.js +7 -7
  22. package/dist/src/server/tools/ask.js.map +1 -1
  23. package/dist/src/server/tools/ast-grep.js +2 -2
  24. package/dist/src/server/tools/ast-grep.js.map +1 -1
  25. package/dist/src/server/tools/audit.js +5 -5
  26. package/dist/src/server/tools/audit.js.map +1 -1
  27. package/dist/src/server/tools/clusters.js +3 -3
  28. package/dist/src/server/tools/clusters.js.map +1 -1
  29. package/dist/src/server/tools/concepts.js +6 -6
  30. package/dist/src/server/tools/concepts.js.map +1 -1
  31. package/dist/src/server/tools/context.js +7 -7
  32. package/dist/src/server/tools/context.js.map +1 -1
  33. package/dist/src/server/tools/critique.js +4 -4
  34. package/dist/src/server/tools/critique.js.map +1 -1
  35. package/dist/src/server/tools/ctx-handles.js +3 -3
  36. package/dist/src/server/tools/ctx-handles.js.map +1 -1
  37. package/dist/src/server/tools/dependencies.js +3 -3
  38. package/dist/src/server/tools/dependencies.js.map +1 -1
  39. package/dist/src/server/tools/diff-search.js +2 -2
  40. package/dist/src/server/tools/diff-search.js.map +1 -1
  41. package/dist/src/server/tools/find-references.js +3 -3
  42. package/dist/src/server/tools/find-references.js.map +1 -1
  43. package/dist/src/server/tools/forget.js +3 -3
  44. package/dist/src/server/tools/forget.js.map +1 -1
  45. package/dist/src/server/tools/impact.js +1 -1
  46. package/dist/src/server/tools/impact.js.map +1 -1
  47. package/dist/src/server/tools/index-status.js +21 -21
  48. package/dist/src/server/tools/index-status.js.map +1 -1
  49. package/dist/src/server/tools/investigate.js +5 -5
  50. package/dist/src/server/tools/investigate.js.map +1 -1
  51. package/dist/src/server/tools/list-repos.js +1 -1
  52. package/dist/src/server/tools/list-repos.js.map +1 -1
  53. package/dist/src/server/tools/lookup.js +4 -4
  54. package/dist/src/server/tools/lookup.js.map +1 -1
  55. package/dist/src/server/tools/memories.js +3 -3
  56. package/dist/src/server/tools/memories.js.map +1 -1
  57. package/dist/src/server/tools/overview.js +3 -3
  58. package/dist/src/server/tools/overview.js.map +1 -1
  59. package/dist/src/server/tools/patterns.js +1 -1
  60. package/dist/src/server/tools/patterns.js.map +1 -1
  61. package/dist/src/server/tools/pin.js +2 -2
  62. package/dist/src/server/tools/pin.js.map +1 -1
  63. package/dist/src/server/tools/post-filter.js +3 -3
  64. package/dist/src/server/tools/post-filter.js.map +1 -1
  65. package/dist/src/server/tools/recall.js +4 -4
  66. package/dist/src/server/tools/recall.js.map +1 -1
  67. package/dist/src/server/tools/remember.js +2 -2
  68. package/dist/src/server/tools/remember.js.map +1 -1
  69. package/dist/src/server/tools/review-diff.js +5 -5
  70. package/dist/src/server/tools/review-diff.js.map +1 -1
  71. package/dist/src/server/tools/search-iterative.js +10 -10
  72. package/dist/src/server/tools/search-iterative.js.map +1 -1
  73. package/dist/src/server/tools/search.js +5 -5
  74. package/dist/src/server/tools/search.js.map +1 -1
  75. package/dist/src/server/tools/test-map.js +3 -3
  76. package/dist/src/server/tools/test-map.js.map +1 -1
  77. package/dist/src/server/tools/tier.js +4 -4
  78. package/dist/src/server/tools/tier.js.map +1 -1
  79. package/dist/src/server/tools/verify.js +4 -4
  80. package/dist/src/server/tools/verify.js.map +1 -1
  81. package/dist/src/server/tools/wakeup.js +3 -3
  82. package/dist/src/server/tools/wakeup.js.map +1 -1
  83. package/dist/src/server/trajectory.js +20 -8
  84. package/dist/src/server/trajectory.js.map +1 -1
  85. package/package.json +1 -1
  86. package/src/skills/sverklo-onboard.md +4 -4
  87. package/src/skills/sverklo-refactor.md +5 -5
  88. package/src/skills/sverklo-review.md +3 -3
@@ -50,7 +50,7 @@ if (command && command !== "--help" && command !== "-h") {
50
50
  const wantsHelp = args.slice(1).some((a) => a === "--help" || a === "-h");
51
51
  if (wantsHelp) {
52
52
  const HELP_BLURBS = {
53
- init: "Set up sverklo in your project (.mcp.json + CLAUDE.md, auto-detects Claude Code/Cursor/Windsurf/Antigravity).",
53
+ init: "Set up sverklo in your project (.mcp.json + CLAUDE.md, auto-detects Claude Code/Cursor/Windsurf/Antigravity). With --global: one-time-per-machine setup — write SVERKLO_SNIPPET to ~/.claude/CLAUDE.md and ~/.codex/AGENTS.md, register the project, gitignore .sverklo/, import memories. Skips per-project boilerplate.",
54
54
  doctor: "Diagnose MCP setup issues. Run after `init` to verify the agent can reach sverklo.",
55
55
  audit: "Run codebase audit and emit a graded report. Flags: --format markdown|html|json|graph|arch|obsidian, --output PATH, --open, --badge, --publish.",
56
56
  "audit-diff": "Incremental architectural quality gate. Audits `git diff` for new cycles + fan-in spikes. Flags: --against REF, --fan-in-threshold N, --format human|json, --show-existing, --verbose. Exits 1 on regression.",
@@ -68,7 +68,7 @@ if (command && command !== "--help" && command !== "-h") {
68
68
  wakeup: "Print compressed project context (for system-prompt injection in non-MCP clients).",
69
69
  digest: "5-line summary of what changed in this project. Flags: --since 7d, --format markdown|plain.",
70
70
  receipt: "Token-spend receipt for your recent Claude Code sessions. Shows where tokens went and projected yearly cost. Flags: --since 7d, --format plain|json.",
71
- memory: "Manage the memory store. Subcommands: show, edit, export.",
71
+ memory: "Manage the memory store. Subcommands: show, edit, import, export.",
72
72
  grammars: "Manage tree-sitter grammars for the SVERKLO_PARSER=tree-sitter opt-in path. Subcommands: install.",
73
73
  weights: "Inspect .sverklo.yaml weight rules. Subcommands: explain <path> — show which glob matched and the effective weight.",
74
74
  "audit-prompt": "Print a ready-to-paste codebase-audit prompt (hybrid agent workflow).",
@@ -117,12 +117,24 @@ if (command === "--version" || command === "-v" || command === "-V") {
117
117
  process.exit(0);
118
118
  }
119
119
  if (command === "init") {
120
- // Parse flags: --auto-capture, --mine-chats
120
+ // Parse flags: --auto-capture, --mine-chats, --global
121
121
  const flags = args.filter((a) => a.startsWith("--"));
122
122
  const positional = args.filter((a) => !a.startsWith("--"));
123
123
  const autoCapture = flags.includes("--auto-capture");
124
124
  const mineChats = flags.includes("--mine-chats");
125
+ const isGlobal = flags.includes("--global");
125
126
  const projectPath = resolve(positional[1] || process.cwd());
127
+ if (isGlobal) {
128
+ // Issue #72 — one-time-per-machine setup. Writes SVERKLO_SNIPPET to
129
+ // global agent-instruction locations (~/.claude/CLAUDE.md, ~/.codex/AGENTS.md),
130
+ // registers the project, gitignores .sverklo/, imports memories.
131
+ // Skips per-project boilerplate (.mcp.json, project AGENTS.md/CLAUDE.md,
132
+ // .claude/settings.local.json, skills, copilot/antigravity/codex configs,
133
+ // doctor).
134
+ const { initGlobal } = await import("../src/init-global.js");
135
+ await initGlobal(projectPath, { mineChats });
136
+ process.exit(0);
137
+ }
126
138
  const { initProject } = await import("../src/init.js");
127
139
  await initProject(projectPath, { autoCapture, mineChats });
128
140
  // Auto-register in the global registry
@@ -857,7 +869,7 @@ if (command === "telemetry") {
857
869
  console.log(" os darwin / linux / win32");
858
870
  console.log(" node_major the Node major version sverklo is running on");
859
871
  console.log(" event one of 17 fixed event types");
860
- console.log(" tool sverklo_* tool name (when applicable)");
872
+ console.log(" tool sverklo tool name (when applicable)");
861
873
  console.log(" outcome ok / error / timeout");
862
874
  console.log(" duration_ms tool execution time");
863
875
  console.log("");
@@ -1072,7 +1084,7 @@ if (command === "profile") {
1072
1084
  console.log(` ${tools.map((t) => t.replace(/^sverklo_/, "")).join(", ")}`);
1073
1085
  console.log();
1074
1086
  }
1075
- console.log(" full 36 tools (all sverklo_* tools — default)");
1087
+ console.log(" full 36 tools (every first-party sverklo tool — default)");
1076
1088
  console.log("\n Set with: SVERKLO_PROFILE=core sverklo init");
1077
1089
  console.log(" Or in .sverklo.yaml: profile: core");
1078
1090
  console.log(" See: https://sverklo.com/blog/we-already-shipped-mcp-code-mode/\n");
@@ -1100,8 +1112,14 @@ if (command === "profile") {
1100
1112
  // Structured doc — use it directly. The --days window doesn't apply
1101
1113
  // to cumulative stats; we use the full lifetime instead, and tell
1102
1114
  // the user when the doc started accumulating.
1115
+ //
1116
+ // v0.28.0: canonicalize legacy `sverklo_*` names in historical stats
1117
+ // files so they collapse onto the new short names (`sverklo_search`
1118
+ // + `search` → `search`). Without this, a long-running user's stats
1119
+ // would show duplicate rows after the rename.
1103
1120
  for (const [tool, stat] of Object.entries(structuredStats.tools)) {
1104
- counts[tool] = stat.calls;
1121
+ const canon = tool.startsWith("sverklo_") ? tool.slice("sverklo_".length) : tool;
1122
+ counts[canon] = (counts[canon] || 0) + stat.calls;
1105
1123
  }
1106
1124
  total = structuredStats.totalCalls;
1107
1125
  const sinceStr = new Date(structuredStats.startedAt).toISOString().slice(0, 10);
@@ -1122,7 +1140,10 @@ if (command === "profile") {
1122
1140
  process.exit(0);
1123
1141
  }
1124
1142
  for (const c of calls) {
1125
- const tool = String(c.detail.tool);
1143
+ const raw = String(c.detail.tool);
1144
+ // v0.28.0: collapse legacy `sverklo_*` rows onto canonical names so
1145
+ // upgraded users don't see split-personality stats.
1146
+ const tool = raw.startsWith("sverklo_") ? raw.slice("sverklo_".length) : raw;
1126
1147
  counts[tool] = (counts[tool] || 0) + 1;
1127
1148
  }
1128
1149
  total = calls.length;
@@ -1135,8 +1156,7 @@ if (command === "profile") {
1135
1156
  console.log(" " + "-".repeat(70));
1136
1157
  for (const [tool, n] of ranked) {
1137
1158
  const pct = ((n / total) * 100).toFixed(1) + "%";
1138
- const display = tool.startsWith("sverklo_") ? tool : tool;
1139
- console.log(" " + display.padEnd(38) + String(n).padStart(10) + pct.padStart(10));
1159
+ console.log(" " + tool.padEnd(38) + String(n).padStart(10) + pct.padStart(10));
1140
1160
  }
1141
1161
  console.log(" " + "-".repeat(70));
1142
1162
  // Compute coverage for every named profile so the user can see the
@@ -1145,6 +1165,15 @@ if (command === "profile") {
1145
1165
  // of real usage calls fall outside the profile.
1146
1166
  const profileOrder = ["core", "nav", "review", "lean", "research"];
1147
1167
  const fits = [];
1168
+ // v0.28.0: first-party tools no longer carry a `sverklo_` prefix, so
1169
+ // "missing from profile" is anyone-not-in-profile minus the Zilliz
1170
+ // compat aliases (recorded but not first-party).
1171
+ const COMPAT_ALIASES = new Set([
1172
+ "index_codebase",
1173
+ "search_code",
1174
+ "clear_index",
1175
+ "get_indexing_status",
1176
+ ]);
1148
1177
  for (const name of profileOrder) {
1149
1178
  const profileTools = PROFILES[name];
1150
1179
  if (!profileTools)
@@ -1155,7 +1184,7 @@ if (command === "profile") {
1155
1184
  for (const [tool, n] of ranked) {
1156
1185
  if (profileSet.has(tool))
1157
1186
  covered += n;
1158
- else if (tool.startsWith("sverklo_"))
1187
+ else if (!COMPAT_ALIASES.has(tool))
1159
1188
  missing.push(tool);
1160
1189
  }
1161
1190
  fits.push({ name, size: profileTools.length, coveragePct: covered / total, missing });
@@ -2051,20 +2080,76 @@ if (command === "memory") {
2051
2080
  // show — print memory rows as markdown to stdout
2052
2081
  // edit — open memory rows in $EDITOR; round-trip content edits back
2053
2082
  // to SQLite. Never deletes by omission.
2083
+ // import — scan CLAUDE.md / .cursorrules / ADRs / git log into the
2084
+ // memory store. Wraps `importExistingMemories()`; useful
2085
+ // after `sverklo init --global` to retroactively pull in
2086
+ // a project's existing knowledge.
2054
2087
  const sub = args[1];
2055
- if (sub !== "export" && sub !== "show" && sub !== "edit") {
2056
- console.log(`\nsverklo memory — read, edit, and export the memory store\n\n` +
2088
+ if (sub !== "export" && sub !== "show" && sub !== "edit" && sub !== "import") {
2089
+ console.log(`\nsverklo memory — read, edit, import, and export the memory store\n\n` +
2057
2090
  `Subcommands:\n` +
2058
2091
  ` show print all memories as markdown to stdout\n` +
2059
2092
  ` edit open memories in $EDITOR; round-trip text edits back\n` +
2093
+ ` import scan CLAUDE.md / .cursorrules / ADRs / git log into the store\n` +
2060
2094
  ` export write per-category .md files / JSON / push to Notion\n\n` +
2061
2095
  `Usage:\n` +
2062
2096
  ` sverklo memory show [--include-invalidated]\n` +
2063
2097
  ` sverklo memory edit [--editor PATH]\n` +
2098
+ ` sverklo memory import [path] [--mine-chats]\n` +
2064
2099
  ` sverklo memory export --format markdown|notion|json --to PATH [flags]\n\n` +
2065
2100
  `Run \`sverklo memory <subcommand> --help\` for the full flag list.\n`);
2066
2101
  process.exit(0);
2067
2102
  }
2103
+ if (sub === "import") {
2104
+ // Issue #72 follow-up (HaleTom 2026-05-25): standalone CLI entry to
2105
+ // `importExistingMemories()`. Useful for users who did global setup
2106
+ // elsewhere and just want to pull a project's existing notes into
2107
+ // the memory store without running the kitchen-sink `sverklo init`.
2108
+ const flags = args.slice(2);
2109
+ if (flags.includes("--help") || flags.includes("-h")) {
2110
+ console.log(`\nsverklo memory import — scan project sources into the memory store\n\n` +
2111
+ `Scans (in priority order):\n` +
2112
+ ` CLAUDE.md, AGENTS.md, .cursorrules, .windsurfrules\n` +
2113
+ ` docs/ARCHITECTURE.md, CONTRIBUTING.md\n` +
2114
+ ` docs/adr/, docs/decisions/, adr/, decisions/ (every .md becomes a memory)\n` +
2115
+ ` git log (last 50 conventional commits)\n\n` +
2116
+ `Idempotent: re-imports skip duplicates by content hash.\n\n` +
2117
+ `Usage:\n` +
2118
+ ` sverklo memory import [path] (default: current directory)\n` +
2119
+ ` sverklo memory import . --mine-chats (also scan Claude Code chat transcripts)\n`);
2120
+ process.exit(0);
2121
+ }
2122
+ const positional = flags.filter((a) => !a.startsWith("--"));
2123
+ const mineChats = flags.includes("--mine-chats");
2124
+ const projectPath = resolve(positional[0] || process.cwd());
2125
+ const { getProjectConfig } = await import("../src/utils/config.js");
2126
+ const { Indexer } = await import("../src/indexer/indexer.js");
2127
+ const { importExistingMemories } = await import("../src/memory/import.js");
2128
+ const config = getProjectConfig(projectPath);
2129
+ const indexer = new Indexer(config);
2130
+ try {
2131
+ const result = await importExistingMemories(indexer, projectPath, { mineChats });
2132
+ if (result.imported > 0) {
2133
+ console.log(`Imported ${result.imported} memories from:`);
2134
+ for (const src of result.sources) {
2135
+ console.log(` · ${src}`);
2136
+ }
2137
+ if (result.skipped > 0) {
2138
+ console.log(`(${result.skipped} duplicates skipped)`);
2139
+ }
2140
+ }
2141
+ else {
2142
+ const hint = mineChats
2143
+ ? "No CLAUDE.md, .cursorrules, ADRs, or matching Claude Code chats found — nothing imported."
2144
+ : "No CLAUDE.md, .cursorrules, or ADRs found — nothing imported.";
2145
+ console.log(hint);
2146
+ }
2147
+ }
2148
+ finally {
2149
+ indexer.close();
2150
+ }
2151
+ process.exit(0);
2152
+ }
2068
2153
  if (sub === "show") {
2069
2154
  // Render every active memory as markdown to stdout. AI Edge's
2070
2155
  // "open Memory.md and read it" workflow, but driven by SQLite —