@curiousnerd/keel 0.1.0 → 0.2.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.
package/README.md CHANGED
@@ -80,13 +80,16 @@ keel check /path/to/your/project # any JavaScript, TypeScript, or Python
80
80
  That's it. Run it again any time — it remembers what it already scanned, so repeat
81
81
  runs are nearly instant.
82
82
 
83
- **From source** (for contributing):
83
+ **From source** (clone & build — for contributing, or to run without installing from npm):
84
84
 
85
85
  ```bash
86
- git clone <this-repo> keel && cd keel
87
- npm install
88
- npm run build
89
- node dist/cli.js check /path/to/your/project
86
+ git clone https://github.com/aditya20t/Keel.git keel && cd keel
87
+ npm install # install dependencies
88
+ npm run build # compile TypeScript to dist/
89
+ npm link # optional: makes `keel` available globally
90
+
91
+ keel check /path/to/your/project # if you ran `npm link`
92
+ node dist/cli.js check /path/to/your/project # otherwise, run the built file directly
90
93
  ```
91
94
 
92
95
  ### Commands and options
@@ -245,6 +248,10 @@ languages.
245
248
 
246
249
  Want to help or understand the internals? See [CONTRIBUTING.md](CONTRIBUTING.md).
247
250
 
251
+ ## Credits
252
+
253
+ Built by **Aditya**, with the help of **awesome Claude** 🤖.
254
+
248
255
  ## License
249
256
 
250
257
  [MIT](LICENSE)
package/dist/cli.js CHANGED
@@ -1,7 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from "commander";
3
3
  import pc from "picocolors";
4
- import { resolve } from "node:path";
4
+ import { resolve, dirname, join, basename } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { createSpinner } from "./util/spinner.js";
5
7
  import { loadConfig } from "./config.js";
6
8
  import { loadFacts } from "./extract/scan.js";
7
9
  import { parseClaims } from "./claims/parseBlock.js";
@@ -11,17 +13,27 @@ import { renderText, sortFindings, DEFAULT_FINDING_LIMIT } from "./report/text.j
11
13
  import { renderJson } from "./report/json.js";
12
14
  import { renderMarkdown, improvementSummary } from "./report/markdown.js";
13
15
  import { suggestImprovements } from "./llm/improve.js";
14
- import { writeFileSync } from "node:fs";
16
+ import { readFileSync, writeFileSync } from "node:fs";
15
17
  import { resolveProvider } from "./llm/provider.js";
16
18
  import { LLMCache } from "./llm/cache.js";
17
19
  import { explainFindings } from "./llm/explain.js";
18
20
  import { extractClaimsFromDocs, mergeInferredClaims } from "./llm/claimsFromDocs.js";
19
21
  import { startMcpServer } from "./mcp/server.js";
22
+ /** Read the real version from package.json (works from source and when installed). */
23
+ function packageVersion() {
24
+ try {
25
+ const pkgPath = join(dirname(fileURLToPath(import.meta.url)), "..", "package.json");
26
+ return JSON.parse(readFileSync(pkgPath, "utf8")).version ?? "0.0.0";
27
+ }
28
+ catch {
29
+ return "0.0.0";
30
+ }
31
+ }
20
32
  const program = new Command();
21
33
  program
22
34
  .name("keel")
23
35
  .description("A local-first verifier that keeps an AI coding agent honest.")
24
- .version("0.0.0");
36
+ .version(packageVersion());
25
37
  program
26
38
  .command("check", { isDefault: true })
27
39
  .description("Scan a repo and report drift, library conflicts, and duplication.")
@@ -40,6 +52,8 @@ program
40
52
  const root = resolve(path);
41
53
  const config = loadConfig(root);
42
54
  const respectGitignore = opts.gitignore === false ? false : config.scan.respectGitignore;
55
+ const spinner = createSpinner();
56
+ spinner.start(`Scanning ${basename(root)}…`);
43
57
  // LLM setup (once) — off by default; powers both Tier-2 doc-claim extraction
44
58
  // and plain-language explanations. Resolved before analyze so inferred claims
45
59
  // can flow through the deterministic drift engine.
@@ -58,13 +72,16 @@ program
58
72
  let durationMs = Number(process.hrtime.bigint() - t0) / 1e6;
59
73
  // Tier-2 doc drift: extend claims with ones the LLM infers from prose (untimed).
60
74
  if (provider && llmCache) {
75
+ spinner.update("Reading docs for stated stack…");
61
76
  const inferred = await extractClaimsFromDocs(root, config, provider, llmCache);
62
77
  claims = { ...claims, stack: mergeInferredClaims(claims.stack, inferred) };
63
78
  }
79
+ spinner.update("Analyzing…");
64
80
  const analyzeStart = process.hrtime.bigint();
65
81
  const { findings, score, breakdown } = analyze(facts, claims, config, suppressions);
66
82
  durationMs += Number(process.hrtime.bigint() - analyzeStart) / 1e6;
67
83
  if (opts.facts) {
84
+ spinner.stop();
68
85
  process.stdout.write(JSON.stringify(facts, null, 2) + "\n");
69
86
  return;
70
87
  }
@@ -76,16 +93,19 @@ program
76
93
  };
77
94
  // LLM extras (off by default): per-finding explanations + how-to-improve plan.
78
95
  if (provider && llmCache && findings.length > 0) {
96
+ spinner.update(`Asking ${llmLabel} for explanations…`);
79
97
  const limit = opts.limit && opts.limit > 0 ? opts.limit : DEFAULT_FINDING_LIMIT;
80
98
  await explainFindings(sortFindings(findings).slice(0, limit), provider, llmCache);
81
99
  }
82
100
  let improvement = improvementSummary(report);
83
101
  if (provider && llmCache) {
102
+ spinner.update("Generating improvement plan…");
84
103
  const plan = await suggestImprovements(report, provider, llmCache);
85
104
  if (plan)
86
105
  improvement = plan;
87
106
  }
88
107
  llmCache?.save();
108
+ spinner.stop();
89
109
  // Optional full Markdown report — written to the cwd, never into the scanned repo.
90
110
  let reportFile;
91
111
  if (opts.outputMd !== undefined) {
@@ -130,6 +150,8 @@ program
130
150
  await startMcpServer(resolve(path));
131
151
  });
132
152
  program.parseAsync(process.argv).catch((err) => {
153
+ if (process.stderr.isTTY)
154
+ process.stderr.write("\r\x1b[K"); // clear any spinner line
133
155
  process.stderr.write(pc.red(`keel: ${err instanceof Error ? err.message : String(err)}\n`));
134
156
  process.exitCode = 1;
135
157
  });
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface Spinner {
2
+ start(label: string): void;
3
+ update(label: string): void;
4
+ stop(): void;
5
+ }
6
+ /**
7
+ * A minimal terminal spinner that writes to stderr, so it never interferes with
8
+ * the report on stdout (`--json`, `--output-md`, pipes). It only animates on an
9
+ * interactive TTY — in CI, pipes, or when NO_COLOR is set it's a silent no-op,
10
+ * keeping logs clean. The first frame is drawn synchronously so a message is
11
+ * visible even before a synchronous workload blocks the event loop.
12
+ */
13
+ export declare function createSpinner(stream?: NodeJS.WriteStream): Spinner;
@@ -0,0 +1,48 @@
1
+ import pc from "picocolors";
2
+ const FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
3
+ const INTERVAL_MS = 80;
4
+ /**
5
+ * A minimal terminal spinner that writes to stderr, so it never interferes with
6
+ * the report on stdout (`--json`, `--output-md`, pipes). It only animates on an
7
+ * interactive TTY — in CI, pipes, or when NO_COLOR is set it's a silent no-op,
8
+ * keeping logs clean. The first frame is drawn synchronously so a message is
9
+ * visible even before a synchronous workload blocks the event loop.
10
+ */
11
+ export function createSpinner(stream = process.stderr) {
12
+ const enabled = stream.isTTY === true && !process.env.NO_COLOR && !process.env.CI;
13
+ let timer;
14
+ let frame = 0;
15
+ let label = "";
16
+ const render = () => {
17
+ stream.write(`\r${pc.cyan(FRAMES[frame % FRAMES.length])} ${label}\x1b[K`);
18
+ };
19
+ return {
20
+ start(text) {
21
+ if (!enabled)
22
+ return;
23
+ label = text;
24
+ frame = 0;
25
+ render(); // draw immediately, before any sync work blocks the loop
26
+ timer = setInterval(() => {
27
+ frame += 1;
28
+ render();
29
+ }, INTERVAL_MS);
30
+ timer.unref?.(); // never keep the process alive on our account
31
+ },
32
+ update(text) {
33
+ if (!enabled)
34
+ return;
35
+ label = text;
36
+ render();
37
+ },
38
+ stop() {
39
+ if (!enabled)
40
+ return;
41
+ if (timer)
42
+ clearInterval(timer);
43
+ timer = undefined;
44
+ stream.write("\r\x1b[K"); // clear the spinner line
45
+ },
46
+ };
47
+ }
48
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/util/spinner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAClE,MAAM,WAAW,GAAG,EAAE,CAAC;AAQvB;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,SAA6B,OAAO,CAAC,MAAM;IACvE,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;IAClF,IAAI,KAAiC,CAAC;IACtC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,GAAG,EAAE,CAAC;IAEf,MAAM,MAAM,GAAG,GAAS,EAAE;QACxB,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAE,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;IAC9E,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,CAAC,IAAI;YACR,IAAI,CAAC,OAAO;gBAAE,OAAO;YACrB,KAAK,GAAG,IAAI,CAAC;YACb,KAAK,GAAG,CAAC,CAAC;YACV,MAAM,EAAE,CAAC,CAAC,yDAAyD;YACnE,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;gBACvB,KAAK,IAAI,CAAC,CAAC;gBACX,MAAM,EAAE,CAAC;YACX,CAAC,EAAE,WAAW,CAAC,CAAC;YAChB,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,8CAA8C;QACjE,CAAC;QACD,MAAM,CAAC,IAAI;YACT,IAAI,CAAC,OAAO;gBAAE,OAAO;YACrB,KAAK,GAAG,IAAI,CAAC;YACb,MAAM,EAAE,CAAC;QACX,CAAC;QACD,IAAI;YACF,IAAI,CAAC,OAAO;gBAAE,OAAO;YACrB,IAAI,KAAK;gBAAE,aAAa,CAAC,KAAK,CAAC,CAAC;YAChC,KAAK,GAAG,SAAS,CAAC;YAClB,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,yBAAyB;QACrD,CAAC;KACF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,10 +1,18 @@
1
1
  {
2
2
  "name": "@curiousnerd/keel",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "A local-first verifier that keeps an AI coding agent honest: catches drift, library conflicts, and duplication across JS/TS and Python.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "Aditya",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/aditya20t/Keel.git"
11
+ },
12
+ "homepage": "https://github.com/aditya20t/Keel#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/aditya20t/Keel/issues"
15
+ },
8
16
  "keywords": [
9
17
  "ai",
10
18
  "coding-agent",