semlint-cli 0.1.0 → 0.1.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/README.md +25 -0
- package/dist/cli.js +40 -4
- package/dist/init.js +78 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -21,6 +21,12 @@ pnpm build
|
|
|
21
21
|
semlint check
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
Scaffold a project config with automatic coding agent CLI detection:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
semlint init
|
|
28
|
+
```
|
|
29
|
+
|
|
24
30
|
If running from source:
|
|
25
31
|
|
|
26
32
|
```bash
|
|
@@ -38,6 +44,7 @@ pnpm check
|
|
|
38
44
|
- `--fail-on <error|warn|never>`: failure threshold (default `error`)
|
|
39
45
|
- `--batch`: run all selected rules in one backend call
|
|
40
46
|
- `--debug`: enable debug logs to stderr
|
|
47
|
+
- `init --force`: overwrite an existing `semlint.json`
|
|
41
48
|
|
|
42
49
|
Default diff behavior (without `--base`/`--head`) uses your local branch state:
|
|
43
50
|
|
|
@@ -92,6 +99,24 @@ Unknown fields are ignored.
|
|
|
92
99
|
}
|
|
93
100
|
```
|
|
94
101
|
|
|
102
|
+
## Config scaffolding and auto-detection
|
|
103
|
+
|
|
104
|
+
Run:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
semlint init
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
This creates `./semlint.json` and auto-detects installed coding agent CLIs in this priority order:
|
|
111
|
+
|
|
112
|
+
1. `cursor` -> backend `cursor-cli`
|
|
113
|
+
2. `claude` -> backend `claude-code`
|
|
114
|
+
3. `codex` -> backend `codex-cli`
|
|
115
|
+
|
|
116
|
+
If no known CLI is detected, Semlint falls back to `cursor-cli` + executable `cursor`.
|
|
117
|
+
|
|
118
|
+
Use `semlint init --force` to overwrite an existing config file.
|
|
119
|
+
|
|
95
120
|
## Rule files
|
|
96
121
|
|
|
97
122
|
Rule JSON files are loaded from `rules/`.
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const init_1 = require("./init");
|
|
4
5
|
const main_1 = require("./main");
|
|
6
|
+
const HELP_TEXT = [
|
|
7
|
+
"Usage:",
|
|
8
|
+
" semlint check [--backend <name>] [--model <name>] [--config <path>] [--format <text|json>] [--base <ref>] [--head <ref>] [--fail-on <error|warn|never>] [--batch] [--debug]",
|
|
9
|
+
" semlint init [--force]",
|
|
10
|
+
" semlint --help",
|
|
11
|
+
"",
|
|
12
|
+
"Commands:",
|
|
13
|
+
" check Run semantic lint rules against your git diff",
|
|
14
|
+
" init Create semlint.json with auto-detected agent backend",
|
|
15
|
+
"",
|
|
16
|
+
"Options:",
|
|
17
|
+
" -h, --help Show this help text"
|
|
18
|
+
].join("\n");
|
|
19
|
+
class HelpRequestedError extends Error {
|
|
20
|
+
constructor() {
|
|
21
|
+
super(HELP_TEXT);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
5
24
|
const FLAGS_WITH_VALUES = new Set([
|
|
6
25
|
"--backend",
|
|
7
26
|
"--model",
|
|
@@ -18,9 +37,26 @@ function isFailOn(value) {
|
|
|
18
37
|
return value === "error" || value === "warn" || value === "never";
|
|
19
38
|
}
|
|
20
39
|
function parseArgs(argv) {
|
|
40
|
+
if (argv.length === 0 || argv.includes("--help") || argv.includes("-h") || argv[0] === "help") {
|
|
41
|
+
throw new HelpRequestedError();
|
|
42
|
+
}
|
|
21
43
|
const [command, ...rest] = argv;
|
|
22
|
-
if (!command || command !== "check") {
|
|
23
|
-
throw new Error(
|
|
44
|
+
if (!command || (command !== "check" && command !== "init")) {
|
|
45
|
+
throw new Error(HELP_TEXT);
|
|
46
|
+
}
|
|
47
|
+
if (command === "init") {
|
|
48
|
+
const options = {
|
|
49
|
+
command: "init",
|
|
50
|
+
debug: false
|
|
51
|
+
};
|
|
52
|
+
for (const token of rest) {
|
|
53
|
+
if (token === "--force") {
|
|
54
|
+
options.force = true;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
throw new Error(`Unknown flag for init: ${token}`);
|
|
58
|
+
}
|
|
59
|
+
return options;
|
|
24
60
|
}
|
|
25
61
|
const options = {
|
|
26
62
|
command: "check",
|
|
@@ -81,13 +117,13 @@ function parseArgs(argv) {
|
|
|
81
117
|
async function main() {
|
|
82
118
|
try {
|
|
83
119
|
const options = parseArgs(process.argv.slice(2));
|
|
84
|
-
const exitCode = await (0, main_1.runSemlint)(options);
|
|
120
|
+
const exitCode = options.command === "init" ? (0, init_1.scaffoldConfig)(options.force) : await (0, main_1.runSemlint)(options);
|
|
85
121
|
process.exitCode = exitCode;
|
|
86
122
|
}
|
|
87
123
|
catch (error) {
|
|
88
124
|
const message = error instanceof Error ? error.message : String(error);
|
|
89
125
|
process.stderr.write(`${message}\n`);
|
|
90
|
-
process.exitCode = 2;
|
|
126
|
+
process.exitCode = error instanceof HelpRequestedError ? 0 : 2;
|
|
91
127
|
}
|
|
92
128
|
}
|
|
93
129
|
void main();
|
package/dist/init.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.scaffoldConfig = scaffoldConfig;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const node_child_process_1 = require("node:child_process");
|
|
10
|
+
function commandExists(command) {
|
|
11
|
+
const result = (0, node_child_process_1.spawnSync)(command, ["--version"], {
|
|
12
|
+
stdio: "ignore"
|
|
13
|
+
});
|
|
14
|
+
return result.status === 0 || result.status === 1;
|
|
15
|
+
}
|
|
16
|
+
function detectBackend() {
|
|
17
|
+
const candidates = [
|
|
18
|
+
{
|
|
19
|
+
executable: "cursor",
|
|
20
|
+
backend: "cursor-cli",
|
|
21
|
+
reason: "detected Cursor CLI"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
executable: "claude",
|
|
25
|
+
backend: "claude-code",
|
|
26
|
+
reason: "detected Claude Code CLI"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
executable: "codex",
|
|
30
|
+
backend: "codex-cli",
|
|
31
|
+
reason: "detected Codex CLI"
|
|
32
|
+
}
|
|
33
|
+
];
|
|
34
|
+
for (const candidate of candidates) {
|
|
35
|
+
if (commandExists(candidate.executable)) {
|
|
36
|
+
return candidate;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
backend: "cursor-cli",
|
|
41
|
+
executable: "cursor",
|
|
42
|
+
reason: "no known agent CLI detected, using default Cursor setup"
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function scaffoldConfig(force = false) {
|
|
46
|
+
const targetPath = node_path_1.default.join(process.cwd(), "semlint.json");
|
|
47
|
+
if (node_fs_1.default.existsSync(targetPath) && !force) {
|
|
48
|
+
process.stderr.write(`Refusing to overwrite existing ${targetPath}. Re-run with "semlint init --force" to replace it.\n`);
|
|
49
|
+
return 2;
|
|
50
|
+
}
|
|
51
|
+
const detected = detectBackend();
|
|
52
|
+
const scaffold = {
|
|
53
|
+
backend: detected.backend,
|
|
54
|
+
model: "auto",
|
|
55
|
+
budgets: {
|
|
56
|
+
timeout_ms: 120000
|
|
57
|
+
},
|
|
58
|
+
output: {
|
|
59
|
+
format: "text"
|
|
60
|
+
},
|
|
61
|
+
execution: {
|
|
62
|
+
batch: false
|
|
63
|
+
},
|
|
64
|
+
rules: {
|
|
65
|
+
disable: [],
|
|
66
|
+
severity_overrides: {}
|
|
67
|
+
},
|
|
68
|
+
backends: {
|
|
69
|
+
[detected.backend]: {
|
|
70
|
+
executable: detected.executable
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
node_fs_1.default.writeFileSync(targetPath, `${JSON.stringify(scaffold, null, 2)}\n`, "utf8");
|
|
75
|
+
process.stdout.write(`Created ${targetPath}\n`);
|
|
76
|
+
process.stdout.write(`Backend setup: ${detected.backend} (${detected.reason})\n`);
|
|
77
|
+
return 0;
|
|
78
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "semlint-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Semantic lint CLI — runs LLM-backed rules on your git diff and returns CI-friendly exit codes",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "dist/main.js",
|
|
7
7
|
"bin": {
|
|
8
|
-
"semlint": "dist/cli.js"
|
|
8
|
+
"semlint-cli": "dist/cli.js"
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"dist",
|