flamerjs 0.1.5 → 1.0.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 (3) hide show
  1. package/README.md +72 -32
  2. package/dist/cli.js +80 -2
  3. package/package.json +3 -1
package/README.md CHANGED
@@ -2,10 +2,13 @@
2
2
 
3
3
  **A fast sanity checker for AI-assisted codebases.**
4
4
 
5
- [![CI](https://github.com/dummy3ye/flamer/actions/workflows/ci.yml/badge.svg)](https://github.com/dummy3ye/flamer/actions/workflows/ci.yml)
6
- [![codecov](https://codecov.io/gh/dummy3ye/flamer/branch/master/graph/badge.svg)](https://codecov.io/gh/dummy3ye/flamer)
7
- [![npm](https://img.shields.io/npm/v/flamerjs)](https://www.npmjs.com/package/flamerjs)
8
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
5
+ [![CI](https://img.shields.io/github/actions/workflow/status/dummy3ye/flamer/ci.yml?branch=master&style=for-the-badge&label=CI&labelColor=101418&color=9ccbfb)](https://github.com/dummy3ye/flamer/actions/workflows/ci.yml)
6
+ [![Coverage](https://img.shields.io/codecov/c/github/dummy3ye/flamer?style=for-the-badge&label=coverage&labelColor=101418&color=b9c8da)](https://codecov.io/gh/dummy3ye/flamer)
7
+ [![npm](https://img.shields.io/npm/v/flamerjs?style=for-the-badge&labelColor=101418&color=d3bfe6)](https://www.npmjs.com/package/flamerjs)<br>
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=for-the-badge&labelColor=101418&color=d3bfe6)](LICENSE)
9
+ [![GitHub last commit](https://img.shields.io/github/last-commit/dummy3ye/flamer?style=for-the-badge&labelColor=101418&color=9ccbfb)](https://github.com/dummy3ye/flamer/commits/master)
10
+ [![GitHub Repo stars](https://img.shields.io/github/stars/dummy3ye/flamer?style=for-the-badge&labelColor=101418&color=b9c8da)](https://github.com/dummy3ye/flamer/stargazers)
11
+ [![GitHub repo size](https://img.shields.io/github/repo-size/dummy3ye/flamer?style=for-the-badge&labelColor=101418&color=d3bfe6)](https://github.com/dummy3ye/flamer)
9
12
 
10
13
  Flamer scans a repository for the common mistakes that appear when software is
11
14
  assembled quickly with AI or other “vibe coding” workflows: unfinished
@@ -49,68 +52,79 @@ can be used locally, in pull requests, or in CI.
49
52
  C#, Zig, SQL, notebooks, and additional language profiles.
50
53
  - **Stable JSON output:** suitable for CI annotations and other automation.
51
54
  - **Single-pass scanning:** files are walked once and content is read once.
55
+ - **Optional native workers:** Rust and C++ workers for isolated file metrics,
56
+ with TypeScript remaining the default engine.
52
57
 
53
58
  ## Requirements
54
59
 
55
60
  - Node.js 18 or newer
56
61
  - npm
57
62
 
63
+ The default TypeScript engine needs only Node.js and npm. Native mode additionally
64
+ requires Rust/Cargo for the Rust worker or a C++17 compiler and CMake for the
65
+ C++ worker.
66
+
58
67
  ## Quick start
59
68
 
60
- Run Flamer from a checkout:
69
+ Run the published CLI without installing it permanently:
61
70
 
62
71
  ```bash
63
- npm ci
64
- npm run build
65
- node dist/cli.js .
72
+ npx flamerjs .
66
73
  ```
67
74
 
68
- After publishing, install the CLI globally:
75
+ For a project-local installation, add Flamer as a development dependency:
76
+
77
+ ```bash
78
+ npm install --save-dev flamerjs
79
+ npx flamerjs .
80
+ ```
81
+
82
+ Or install it globally if you use it across repositories:
69
83
 
70
84
  ```bash
71
85
  npm install --global flamerjs
72
86
  flamerjs .
73
87
  ```
74
88
 
75
- During development, `npm run dev` watches and rebuilds `dist/cli.js`.
76
89
  The default output is a colorized terminal summary when run interactively.
77
90
  Use `--format json` for automation and machine-readable output.
78
91
 
79
92
  For a human-readable report:
80
93
 
81
94
  ```bash
82
- node dist/cli.js . --format summary
95
+ flamerjs . --format summary
83
96
  ```
84
97
 
85
98
  Analyze another repository:
86
99
 
87
100
  ```bash
88
- node dist/cli.js /path/to/repository --format summary
101
+ flamerjs /path/to/repository --format summary
89
102
  ```
90
103
 
91
104
  ## CLI
92
105
 
93
106
  ```text
94
- node dist/cli.js [path] [options]
107
+ flamerjs [path] [options]
95
108
  ```
96
109
 
97
- | Option | Description |
98
- | --------------------------- | ----------------------------------------------------------------------------- |
99
- | `--package, --scope <name>` | Analyze only a named sub-project |
100
- | `--path <dir>` | Set the repository root; defaults to the current directory |
101
- | `--format <json\|summary>` | Select JSON or human-readable output; summary is the default |
102
- | `--out <file>` | Also write the JSON report to a file |
103
- | `--fail-on <SEVERITY>` | Exit with status 1 at or above `CRITICAL`, `HIGH`, `MEDIUM`, `LOW`, or `INFO` |
104
- | `--max-files <n>` | Limit the number of files scanned |
105
- | `--commit-limit <n>` | Limit commits inspected by Git checks |
106
- | `--no-git` | Skip Git analysis |
107
- | `--no-lockfile-warning` | Suppress the missing-lockfile suggestion |
108
- | `--ignore-dir <name>` | Ignore an additional directory name; repeatable |
109
- | `--quiet` | Suppress the human summary |
110
- | `--color` | Force ANSI colors |
111
- | `--no-color` | Disable ANSI colors |
112
- | `--list-languages` | List recognized language profiles |
113
- | `--help` | Show command help |
110
+ | Option | Description |
111
+ | ------------------------------------- | ----------------------------------------------------------------------------- |
112
+ | `--package, --scope <name>` | Analyze only a named sub-project |
113
+ | `--path <dir>` | Set the repository root; defaults to the current directory |
114
+ | `--format <json\|summary>` | Select JSON or human-readable output; summary is the default |
115
+ | `--out <file>` | Also write the JSON report to a file |
116
+ | `--fail-on <SEVERITY>` | Exit with status 1 at or above `CRITICAL`, `HIGH`, `MEDIUM`, `LOW`, or `INFO` |
117
+ | `--max-files <n>` | Limit the number of files scanned |
118
+ | `--commit-limit <n>` | Limit commits inspected by Git checks |
119
+ | `--no-git` | Skip Git analysis |
120
+ | `--no-lockfile-warning` | Suppress the missing-lockfile suggestion |
121
+ | `--ignore-dir <name>` | Ignore an additional directory name; repeatable |
122
+ | `--quiet` | Suppress the human summary |
123
+ | `--color` | Force ANSI colors |
124
+ | `--no-color` | Disable ANSI colors |
125
+ | `--engine <typescript\|native\|auto>` | Select the scan engine; TypeScript is the default |
126
+ | `--list-languages` | List recognized language profiles |
127
+ | `--help` | Show command help |
114
128
 
115
129
  Exit status `0` means the scan completed; findings may still exist. Status `1`
116
130
  means `--fail-on` was reached, and status `2` indicates invalid usage or a
@@ -142,25 +156,51 @@ Findings are sorted by severity. Credential values are always redacted.
142
156
 
143
157
  ## Development
144
158
 
159
+ Clone the repository when you want to contribute or work on the scanner itself:
160
+
145
161
  ```bash
146
162
  npm ci
147
- npm run dev # rebuild on source changes
163
+ npm run dev # watch and rebuild dist/cli.js
148
164
  npm test # run the test suite
149
165
  npm run lint
150
166
  npm run format:check
151
167
  npm run build
152
168
  ```
153
169
 
170
+ To run the local build directly:
171
+
172
+ ```bash
173
+ node dist/cli.js .
174
+ ```
175
+
154
176
  The project uses Node.js and npm as its supported development toolchain.
155
177
  `package-lock.json` is the canonical dependency lockfile.
156
178
  The current test suite contains **175 tests**.
157
179
 
180
+ ### Optional native engine
181
+
182
+ Flamer includes an experimental Rust worker for native file metrics. It is
183
+ disabled by default and does not change findings:
184
+
185
+ ```bash
186
+ npm run native:build
187
+ node dist/cli.js . --engine native
188
+ ```
189
+
190
+ Use `--engine auto` to fall back to TypeScript when the worker is unavailable.
191
+ The native protocol and worker details are documented in
192
+ [`native/core/README.md`](native/core/README.md).
193
+
194
+ See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) for the runtime layers,
195
+ worker protocol, engine selection, and native development workflow.
196
+
158
197
  ## How it works
159
198
 
160
199
  1. Detect the repository layout, languages, and ecosystems.
161
200
  2. Walk the tree once and collect file metadata and content-derived signals.
162
201
  3. Run isolated analyzers against the collected records.
163
- 4. Sort findings and emit JSON or a concise summary.
202
+ 4. Optionally collect native file metrics through the versioned worker protocol.
203
+ 5. Sort findings and emit JSON or a concise summary.
164
204
 
165
205
  Analyzers are intentionally factual and conservative. A finding should identify
166
206
  something actionable rather than merely express a preference.
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import { writeFileSync, existsSync as existsSync3 } from "fs";
4
+ import { writeFileSync, existsSync as existsSync4 } from "fs";
5
5
  import { resolve, basename } from "path";
6
6
 
7
7
  // src/util/fs.ts
@@ -2901,6 +2901,42 @@ var ANALYZERS = [
2901
2901
  { id: "systems", label: "Rust / Go / C / C++ / C# / Zig", fn: analyze6 }
2902
2902
  ];
2903
2903
 
2904
+ // src/native.ts
2905
+ import { spawnSync } from "child_process";
2906
+ import { existsSync as existsSync3 } from "fs";
2907
+ import { join as join6 } from "path";
2908
+ function nativeWorkerPath(root) {
2909
+ const configured = process.env.FLAMER_CORE;
2910
+ if (configured) return configured;
2911
+ return join6(root, "native", "core", "rust", "target", "release", "flamer-core");
2912
+ }
2913
+ function runNativeMetrics(root, files) {
2914
+ const worker = nativeWorkerPath(root);
2915
+ if (!existsSync3(worker)) {
2916
+ throw new Error(`native worker not found at ${worker}; run npm run native:build`);
2917
+ }
2918
+ const request = JSON.stringify({ protocol: 1, operation: "file_metrics", root, files });
2919
+ const result = spawnSync(worker, { input: `${request}
2920
+ `, encoding: "utf8", timeout: 3e4 });
2921
+ if (result.error) throw new Error(`native worker failed: ${result.error.message}`);
2922
+ if (result.status !== 0) {
2923
+ throw new Error(`native worker exited with status ${result.status}: ${result.stderr.trim()}`);
2924
+ }
2925
+ let response;
2926
+ try {
2927
+ response = JSON.parse(result.stdout);
2928
+ } catch {
2929
+ throw new Error("native worker returned invalid JSON");
2930
+ }
2931
+ if (response.protocol !== 1 || response.operation !== "file_metrics") {
2932
+ throw new Error("native worker returned an incompatible response");
2933
+ }
2934
+ if (!response.ok) {
2935
+ throw new Error(response.errors.map((error) => `${error.path}: ${error.message}`).join("; "));
2936
+ }
2937
+ return response;
2938
+ }
2939
+
2904
2940
  // src/cli.ts
2905
2941
  var SPEC_VERSION = 1;
2906
2942
  function parseArgs(argv) {
@@ -2918,6 +2954,7 @@ function parseArgs(argv) {
2918
2954
  listLanguages: false,
2919
2955
  help: false,
2920
2956
  color: null,
2957
+ engine: "typescript",
2921
2958
  ignoreDirs: []
2922
2959
  };
2923
2960
  for (let i = 0; i < argv.length; i++) {
@@ -2963,6 +3000,14 @@ function parseArgs(argv) {
2963
3000
  case "--no-color":
2964
3001
  opts.color = false;
2965
3002
  break;
3003
+ case "--engine":
3004
+ opts.engine = argv[++i] || "typescript";
3005
+ if (!["typescript", "native", "auto"].includes(opts.engine)) {
3006
+ process.stderr.write(`invalid engine: ${opts.engine}
3007
+ `);
3008
+ process.exit(2);
3009
+ }
3010
+ break;
2966
3011
  case "--list-languages":
2967
3012
  opts.listLanguages = true;
2968
3013
  break;
@@ -3004,6 +3049,8 @@ Options:
3004
3049
  --quiet suppress the human summary
3005
3050
  --color force ANSI colors
3006
3051
  --no-color disable ANSI colors
3052
+ --engine <typescript|native|auto>
3053
+ choose the scan engine (default: typescript)
3007
3054
  --list-languages print the supported language table
3008
3055
  -h, --help show this help
3009
3056
  `);
@@ -3023,7 +3070,7 @@ ${allExtensions().length} file extensions recognized.
3023
3070
  function run2(opts) {
3024
3071
  const started = Date.now();
3025
3072
  const root = opts.root;
3026
- if (!existsSync3(root) || !isDir(root)) {
3073
+ if (!existsSync4(root) || !isDir(root)) {
3027
3074
  const err = {
3028
3075
  specVersion: SPEC_VERSION,
3029
3076
  tool: "flamer",
@@ -3161,6 +3208,37 @@ function run2(opts) {
3161
3208
  analyzers: analyzerResults
3162
3209
  }
3163
3210
  };
3211
+ if (opts.engine !== "typescript") {
3212
+ try {
3213
+ const native = runNativeMetrics(
3214
+ root,
3215
+ scopedFiles.map((file) => file.rel)
3216
+ );
3217
+ report.metadata.native = {
3218
+ engine: "rust",
3219
+ files: native.metrics.files,
3220
+ bytes: native.metrics.bytes,
3221
+ lines: native.metrics.lines,
3222
+ durationMs: native.duration_ms
3223
+ };
3224
+ } catch (error) {
3225
+ const message = error?.message || String(error);
3226
+ if (opts.engine === "native") {
3227
+ findings.push(
3228
+ finding({
3229
+ category: "error",
3230
+ severity: "CRITICAL",
3231
+ title: "Native engine failed",
3232
+ detail: message
3233
+ })
3234
+ );
3235
+ report.findings = sortFindings(findings);
3236
+ report.metadata.native = { engine: "rust", error: message };
3237
+ return { report, exitCode: 2 };
3238
+ }
3239
+ report.metadata.native = { engine: "typescript", fallback: message };
3240
+ }
3241
+ }
3164
3242
  let exitCode = 0;
3165
3243
  if (opts.failOn && report.metadata.worst && rank(report.metadata.worst) <= rank(opts.failOn)) {
3166
3244
  exitCode = 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flamerjs",
3
- "version": "0.1.5",
3
+ "version": "1.0.0",
4
4
  "description": "Language-agnostic code health auditor that walks a repository once and reports what is wrong with it",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -25,6 +25,8 @@
25
25
  "scripts": {
26
26
  "build": "tsup",
27
27
  "dev": "tsup --watch",
28
+ "native:build": "cargo build --release --manifest-path native/core/rust/Cargo.toml",
29
+ "native:test": "cargo test --manifest-path native/core/rust/Cargo.toml",
28
30
  "prepublishOnly": "npm run lint && npm run build && npm test",
29
31
  "lint": "eslint .",
30
32
  "lint:fix": "eslint . --fix",