@hatem427/code-guard-ci 3.6.0 β 3.6.2
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 +21 -35
- package/config/angular.config.ts +0 -102
- package/dist/config/angular.config.d.ts.map +1 -1
- package/dist/config/angular.config.js +0 -125
- package/dist/config/angular.config.js.map +1 -1
- package/dist/scripts/cli.js +59 -0
- package/dist/scripts/cli.js.map +1 -1
- package/dist/scripts/config-generators/lint-staged-generator.d.ts.map +1 -1
- package/dist/scripts/config-generators/lint-staged-generator.js +8 -2
- package/dist/scripts/config-generators/lint-staged-generator.js.map +1 -1
- package/dist/scripts/install-security-tools.d.ts +14 -0
- package/dist/scripts/install-security-tools.d.ts.map +1 -0
- package/dist/scripts/install-security-tools.js +113 -0
- package/dist/scripts/install-security-tools.js.map +1 -0
- package/dist/scripts/postinstall.js +8 -1
- package/dist/scripts/postinstall.js.map +1 -1
- package/dist/scripts/precommit-check.js +40 -10
- package/dist/scripts/precommit-check.js.map +1 -1
- package/package.json +3 -2
- package/scripts/cli.ts +59 -0
- package/scripts/config-generators/lint-staged-generator.ts +8 -2
- package/scripts/install-security-tools.ts +128 -0
- package/scripts/postinstall.ts +8 -1
- package/scripts/precommit-check.ts +42 -10
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# π‘οΈ Code Guardian β Complete Documentation
|
|
2
2
|
|
|
3
|
-
> **Version:**
|
|
3
|
+
> **Version:** 3.6.0
|
|
4
4
|
> **Package:** `@hatem427/code-guard-ci`
|
|
5
5
|
> **Author:** Hatem Bassem
|
|
6
6
|
> **License:** MIT
|
|
@@ -309,40 +309,26 @@ Code Guardian is designed so that **each tool handles its own domain** with zero
|
|
|
309
309
|
|
|
310
310
|
## 6. CLI Commands
|
|
311
311
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
code-guard
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
code
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
npm run lint # ESLint check
|
|
333
|
-
npm run lint:fix # ESLint auto-fix
|
|
334
|
-
npm run format # Prettier format all
|
|
335
|
-
npm run format:check # Prettier check (no write)
|
|
336
|
-
npm run precommit-check # Run Code Guardian rules manually
|
|
337
|
-
npm run validate # Validate structure + naming
|
|
338
|
-
npm run generate-doc # Generate feature documentation
|
|
339
|
-
npm run generate-pr-checklist # Generate PR checklist
|
|
340
|
-
npm run set-bypass-password # Set bypass password
|
|
341
|
-
npm run set-admin-password # Set admin password
|
|
342
|
-
npm run view-bypass-log # View bypass audit log
|
|
343
|
-
npm run delete-bypass-logs # Delete bypass logs (admin only)
|
|
344
|
-
npm run auto-fix # Auto-fix common issues
|
|
345
|
-
```
|
|
312
|
+
> π **Full command reference:** [COMMANDS.md](COMMANDS.md)
|
|
313
|
+
|
|
314
|
+
All commands are run via `npx code-guard <command>`. Quick overview:
|
|
315
|
+
|
|
316
|
+
| Command | Description |
|
|
317
|
+
|---------|-------------|
|
|
318
|
+
| `init` | Full project setup (ESLint, Prettier, Husky, AI configs, β¦) |
|
|
319
|
+
| `check` | Manually run rule checks (same as pre-commit) |
|
|
320
|
+
| `check-vuln` | 3-layer security audit (npm audit + RetireJS + Grype) |
|
|
321
|
+
| `report` | Open last code quality report in editor |
|
|
322
|
+
| `doc` | Generate feature documentation for current branch |
|
|
323
|
+
| `checklist` | Generate PR checklist from active rules |
|
|
324
|
+
| `validate` | Validate folder structure and file naming |
|
|
325
|
+
| `uninstall` | Remove all generated files (uses manifest) |
|
|
326
|
+
| `add-ai <name>` | Add a single AI assistant config |
|
|
327
|
+
| `list-ai` | List all AI integrations and their status |
|
|
328
|
+
| `version` | Print installed version |
|
|
329
|
+
| `help` | Display usage information |
|
|
330
|
+
|
|
331
|
+
See [COMMANDS.md](COMMANDS.md) for flags, examples, and the full npm scripts reference.
|
|
346
332
|
|
|
347
333
|
---
|
|
348
334
|
|
package/config/angular.config.ts
CHANGED
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
* - RxJS best practices (async pipe, takeUntilDestroyed, signals)
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import * as fs from 'fs';
|
|
14
13
|
import { registerRules, Rule } from './guidelines.config';
|
|
15
14
|
|
|
16
15
|
const angularRules: Rule[] = [
|
|
@@ -78,107 +77,6 @@ const angularRules: Rule[] = [
|
|
|
78
77
|
category: 'Angular Deprecated APIs',
|
|
79
78
|
},
|
|
80
79
|
|
|
81
|
-
// ββ Template best practices ββββββββββββββββββββββββββββββββββββββββββββ
|
|
82
|
-
|
|
83
|
-
{
|
|
84
|
-
id: 'angular-no-function-in-template',
|
|
85
|
-
label: 'No function calls in templates',
|
|
86
|
-
description:
|
|
87
|
-
'Avoid calling functions in Angular templates β they run on every change detection cycle. Use pipes, computed signals, or memoized getters instead.',
|
|
88
|
-
severity: 'error',
|
|
89
|
-
fileExtensions: ['html'],
|
|
90
|
-
pattern: null,
|
|
91
|
-
customCheck: (file) => {
|
|
92
|
-
const violations: Array<{ line: number | null; message: string }> = [];
|
|
93
|
-
|
|
94
|
-
// ββ 1. Discover signals declared in the companion .ts component file ββββ
|
|
95
|
-
//
|
|
96
|
-
// Angular signals (signal, computed, toSignal, input, output, viewChild,
|
|
97
|
-
// contentChild, model) are read by calling them as functions β e.g.
|
|
98
|
-
// loading() β which looks identical to a regular method call in a template.
|
|
99
|
-
// We resolve the companion TypeScript file and extract every identifier
|
|
100
|
-
// that is assigned to a signal factory so we can whitelist those calls.
|
|
101
|
-
const signalNames = new Set<string>();
|
|
102
|
-
const tsFilePath = file.absolutePath.replace(/\.html$/, '.ts');
|
|
103
|
-
try {
|
|
104
|
-
if (fs.existsSync(tsFilePath)) {
|
|
105
|
-
const tsContent = fs.readFileSync(tsFilePath, 'utf-8');
|
|
106
|
-
// Matches class field assignments like:
|
|
107
|
-
// loading = signal(false)
|
|
108
|
-
// readonly isReady = computed(() => ...)
|
|
109
|
-
// data = toSignal(obs$)
|
|
110
|
-
// name = input('') / name = input.required<string>()
|
|
111
|
-
// clicked = output() / el = viewChild('ref') / val = model(0)
|
|
112
|
-
const signalDeclPattern =
|
|
113
|
-
/\b(\w+)\s*=\s*(?:signal|computed|toSignal|input(?:\.required)?|output(?:Required)?|viewChild(?:Required)?|viewChildren|contentChild(?:Required)?|contentChildren|model)\s*[(<]/g;
|
|
114
|
-
let m: RegExpExecArray | null;
|
|
115
|
-
while ((m = signalDeclPattern.exec(tsContent)) !== null) {
|
|
116
|
-
signalNames.add(m[1]);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
} catch {
|
|
120
|
-
// If the companion file cannot be read, fall back to no signal awareness.
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// ββ 2. Helper: returns true when every function call in the expression
|
|
124
|
-
// is either a known signal read or an Angular built-in ($any, $event). ββ
|
|
125
|
-
const ANGULAR_BUILTINS = new Set(['$any', '$event']);
|
|
126
|
-
const allCallsAreSafe = (expression: string): boolean => {
|
|
127
|
-
// Without signal metadata we cannot safely whitelist anything.
|
|
128
|
-
if (signalNames.size === 0) return false;
|
|
129
|
-
const callPattern = /\b(\w+)\s*\(/g;
|
|
130
|
-
let m: RegExpExecArray | null;
|
|
131
|
-
while ((m = callPattern.exec(expression)) !== null) {
|
|
132
|
-
if (!signalNames.has(m[1]) && !ANGULAR_BUILTINS.has(m[1])) {
|
|
133
|
-
return false;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return true;
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
// ββ 3. Scan each line ββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
140
|
-
const interpolationRegex = /\{\{[^}]*\w+\s*\([^)]*\)[^}]*\}\}/g;
|
|
141
|
-
// Property binding regex β excludes event bindings such as (click), (submit) β¦
|
|
142
|
-
const propertyBindingRegex =
|
|
143
|
-
/\[(?!click|submit|keyup|keydown|change|input|focus|blur)\w+\]\s*=\s*"([^"]*)"/g;
|
|
144
|
-
|
|
145
|
-
for (let i = 0; i < file.lines.length; i++) {
|
|
146
|
-
const line = file.lines[i];
|
|
147
|
-
const trimmed = line.trim();
|
|
148
|
-
|
|
149
|
-
// ββ Interpolation: {{ expr() }} βββββββββββββββββββββββββββββββββββββ
|
|
150
|
-
interpolationRegex.lastIndex = 0;
|
|
151
|
-
if (interpolationRegex.test(line)) {
|
|
152
|
-
// Pipes like {{ value | date }} are always safe.
|
|
153
|
-
if (!trimmed.includes(' | ') && !allCallsAreSafe(trimmed)) {
|
|
154
|
-
violations.push({
|
|
155
|
-
line: i + 1,
|
|
156
|
-
message: `Function call in interpolation: "${trimmed}". Use a pipe or computed signal instead.`,
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// ββ Property bindings: [prop]="expr()" ββββββββββββββββββββββββββββββ
|
|
162
|
-
propertyBindingRegex.lastIndex = 0;
|
|
163
|
-
let match: RegExpExecArray | null;
|
|
164
|
-
while ((match = propertyBindingRegex.exec(line)) !== null) {
|
|
165
|
-
const expression = match[1]; // content between the quotes
|
|
166
|
-
if (/\w+\s*\(/.test(expression) && !allCallsAreSafe(expression)) {
|
|
167
|
-
violations.push({
|
|
168
|
-
line: i + 1,
|
|
169
|
-
message: `Function call in property binding: "${trimmed}". Use a signal or computed signal instead.`,
|
|
170
|
-
});
|
|
171
|
-
break; // one violation per line is enough
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return violations;
|
|
177
|
-
},
|
|
178
|
-
applicableTo: ['angular'],
|
|
179
|
-
category: 'Angular Templates',
|
|
180
|
-
},
|
|
181
|
-
|
|
182
80
|
// ββ RxJS best practices ββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
183
81
|
|
|
184
82
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"angular.config.d.ts","sourceRoot":"","sources":["../../config/angular.config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"angular.config.d.ts","sourceRoot":"","sources":["../../config/angular.config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAiB,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE1D,QAAA,MAAM,YAAY,EAAE,IAAI,EA6QvB,CAAC;AAKF,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -10,42 +10,8 @@
|
|
|
10
10
|
* - Function calls in templates
|
|
11
11
|
* - RxJS best practices (async pipe, takeUntilDestroyed, signals)
|
|
12
12
|
*/
|
|
13
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
-
if (k2 === undefined) k2 = k;
|
|
15
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
-
}
|
|
19
|
-
Object.defineProperty(o, k2, desc);
|
|
20
|
-
}) : (function(o, m, k, k2) {
|
|
21
|
-
if (k2 === undefined) k2 = k;
|
|
22
|
-
o[k2] = m[k];
|
|
23
|
-
}));
|
|
24
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
25
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
26
|
-
}) : function(o, v) {
|
|
27
|
-
o["default"] = v;
|
|
28
|
-
});
|
|
29
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
30
|
-
var ownKeys = function(o) {
|
|
31
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
32
|
-
var ar = [];
|
|
33
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
34
|
-
return ar;
|
|
35
|
-
};
|
|
36
|
-
return ownKeys(o);
|
|
37
|
-
};
|
|
38
|
-
return function (mod) {
|
|
39
|
-
if (mod && mod.__esModule) return mod;
|
|
40
|
-
var result = {};
|
|
41
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
42
|
-
__setModuleDefault(result, mod);
|
|
43
|
-
return result;
|
|
44
|
-
};
|
|
45
|
-
})();
|
|
46
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
14
|
exports.angularRules = void 0;
|
|
48
|
-
const fs = __importStar(require("fs"));
|
|
49
15
|
const guidelines_config_1 = require("./guidelines.config");
|
|
50
16
|
const angularRules = [
|
|
51
17
|
// ββ Lifecycle ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -101,97 +67,6 @@ const angularRules = [
|
|
|
101
67
|
applicableTo: ['angular'],
|
|
102
68
|
category: 'Angular Deprecated APIs',
|
|
103
69
|
},
|
|
104
|
-
// ββ Template best practices ββββββββββββββββββββββββββββββββββββββββββββ
|
|
105
|
-
{
|
|
106
|
-
id: 'angular-no-function-in-template',
|
|
107
|
-
label: 'No function calls in templates',
|
|
108
|
-
description: 'Avoid calling functions in Angular templates β they run on every change detection cycle. Use pipes, computed signals, or memoized getters instead.',
|
|
109
|
-
severity: 'error',
|
|
110
|
-
fileExtensions: ['html'],
|
|
111
|
-
pattern: null,
|
|
112
|
-
customCheck: (file) => {
|
|
113
|
-
const violations = [];
|
|
114
|
-
// ββ 1. Discover signals declared in the companion .ts component file ββββ
|
|
115
|
-
//
|
|
116
|
-
// Angular signals (signal, computed, toSignal, input, output, viewChild,
|
|
117
|
-
// contentChild, model) are read by calling them as functions β e.g.
|
|
118
|
-
// loading() β which looks identical to a regular method call in a template.
|
|
119
|
-
// We resolve the companion TypeScript file and extract every identifier
|
|
120
|
-
// that is assigned to a signal factory so we can whitelist those calls.
|
|
121
|
-
const signalNames = new Set();
|
|
122
|
-
const tsFilePath = file.absolutePath.replace(/\.html$/, '.ts');
|
|
123
|
-
try {
|
|
124
|
-
if (fs.existsSync(tsFilePath)) {
|
|
125
|
-
const tsContent = fs.readFileSync(tsFilePath, 'utf-8');
|
|
126
|
-
// Matches class field assignments like:
|
|
127
|
-
// loading = signal(false)
|
|
128
|
-
// readonly isReady = computed(() => ...)
|
|
129
|
-
// data = toSignal(obs$)
|
|
130
|
-
// name = input('') / name = input.required<string>()
|
|
131
|
-
// clicked = output() / el = viewChild('ref') / val = model(0)
|
|
132
|
-
const signalDeclPattern = /\b(\w+)\s*=\s*(?:signal|computed|toSignal|input(?:\.required)?|output(?:Required)?|viewChild(?:Required)?|viewChildren|contentChild(?:Required)?|contentChildren|model)\s*[(<]/g;
|
|
133
|
-
let m;
|
|
134
|
-
while ((m = signalDeclPattern.exec(tsContent)) !== null) {
|
|
135
|
-
signalNames.add(m[1]);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
catch {
|
|
140
|
-
// If the companion file cannot be read, fall back to no signal awareness.
|
|
141
|
-
}
|
|
142
|
-
// ββ 2. Helper: returns true when every function call in the expression
|
|
143
|
-
// is either a known signal read or an Angular built-in ($any, $event). ββ
|
|
144
|
-
const ANGULAR_BUILTINS = new Set(['$any', '$event']);
|
|
145
|
-
const allCallsAreSafe = (expression) => {
|
|
146
|
-
// Without signal metadata we cannot safely whitelist anything.
|
|
147
|
-
if (signalNames.size === 0)
|
|
148
|
-
return false;
|
|
149
|
-
const callPattern = /\b(\w+)\s*\(/g;
|
|
150
|
-
let m;
|
|
151
|
-
while ((m = callPattern.exec(expression)) !== null) {
|
|
152
|
-
if (!signalNames.has(m[1]) && !ANGULAR_BUILTINS.has(m[1])) {
|
|
153
|
-
return false;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return true;
|
|
157
|
-
};
|
|
158
|
-
// ββ 3. Scan each line ββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
159
|
-
const interpolationRegex = /\{\{[^}]*\w+\s*\([^)]*\)[^}]*\}\}/g;
|
|
160
|
-
// Property binding regex β excludes event bindings such as (click), (submit) β¦
|
|
161
|
-
const propertyBindingRegex = /\[(?!click|submit|keyup|keydown|change|input|focus|blur)\w+\]\s*=\s*"([^"]*)"/g;
|
|
162
|
-
for (let i = 0; i < file.lines.length; i++) {
|
|
163
|
-
const line = file.lines[i];
|
|
164
|
-
const trimmed = line.trim();
|
|
165
|
-
// ββ Interpolation: {{ expr() }} βββββββββββββββββββββββββββββββββββββ
|
|
166
|
-
interpolationRegex.lastIndex = 0;
|
|
167
|
-
if (interpolationRegex.test(line)) {
|
|
168
|
-
// Pipes like {{ value | date }} are always safe.
|
|
169
|
-
if (!trimmed.includes(' | ') && !allCallsAreSafe(trimmed)) {
|
|
170
|
-
violations.push({
|
|
171
|
-
line: i + 1,
|
|
172
|
-
message: `Function call in interpolation: "${trimmed}". Use a pipe or computed signal instead.`,
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
// ββ Property bindings: [prop]="expr()" ββββββββββββββββββββββββββββββ
|
|
177
|
-
propertyBindingRegex.lastIndex = 0;
|
|
178
|
-
let match;
|
|
179
|
-
while ((match = propertyBindingRegex.exec(line)) !== null) {
|
|
180
|
-
const expression = match[1]; // content between the quotes
|
|
181
|
-
if (/\w+\s*\(/.test(expression) && !allCallsAreSafe(expression)) {
|
|
182
|
-
violations.push({
|
|
183
|
-
line: i + 1,
|
|
184
|
-
message: `Function call in property binding: "${trimmed}". Use a signal or computed signal instead.`,
|
|
185
|
-
});
|
|
186
|
-
break; // one violation per line is enough
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
return violations;
|
|
191
|
-
},
|
|
192
|
-
applicableTo: ['angular'],
|
|
193
|
-
category: 'Angular Templates',
|
|
194
|
-
},
|
|
195
70
|
// ββ RxJS best practices ββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
196
71
|
{
|
|
197
72
|
id: 'angular-use-async-pipe',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"angular.config.js","sourceRoot":"","sources":["../../config/angular.config.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG
|
|
1
|
+
{"version":3,"file":"angular.config.js","sourceRoot":"","sources":["../../config/angular.config.ts"],"names":[],"mappings":"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"}
|
package/dist/scripts/cli.js
CHANGED
|
@@ -612,6 +612,13 @@ npx lint-staged
|
|
|
612
612
|
|
|
613
613
|
# Run Code Guardian rules
|
|
614
614
|
npm run precommit-check
|
|
615
|
+
|
|
616
|
+
# Run tests for staged source files (skip JSON/config files)
|
|
617
|
+
STAGED=$(git diff --cached --name-only --diff-filter=d | grep -E '\.(ts|js|html|css|scss)$' | grep -v '\.json$')
|
|
618
|
+
if [ -n "$STAGED" ]; then
|
|
619
|
+
echo "π§ͺ Running test coverage for staged source files..."
|
|
620
|
+
npm run test:coverage
|
|
621
|
+
fi
|
|
615
622
|
# --- code-guardian-hook-end ---
|
|
616
623
|
`;
|
|
617
624
|
if (fs.existsSync(preCommitPath)) {
|
|
@@ -1624,42 +1631,94 @@ function runVulnerabilityCheck() {
|
|
|
1624
1631
|
// ββ Main ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
1625
1632
|
(async () => {
|
|
1626
1633
|
switch (command) {
|
|
1634
|
+
// Sets up the entire Code Guardian toolchain in one shot:
|
|
1635
|
+
// ESLint, Prettier, TypeScript strict config, lint-staged, CommitLint,
|
|
1636
|
+
// EditorConfig, VS Code settings, Husky pre-commit hook, and AI assistant
|
|
1637
|
+
// config files (Cursor, Copilot, Claude, Gemini, Windsurfβ¦).
|
|
1638
|
+
// Also patches .gitignore so generated files are tracked correctly.
|
|
1639
|
+
// Usage: npx code-guard init [--skip-hooks] [--skip-ai]
|
|
1627
1640
|
case 'init':
|
|
1628
1641
|
initProject();
|
|
1629
1642
|
break;
|
|
1643
|
+
// Manually runs the same rule checks that fire on every git commit.
|
|
1644
|
+
// Useful for checking your work before staging files.
|
|
1645
|
+
// Scans staged files against all shared + framework-specific rules,
|
|
1646
|
+
// then runs ESLint and Prettier in check mode.
|
|
1647
|
+
// Usage: npx code-guard check
|
|
1630
1648
|
case 'check':
|
|
1631
1649
|
runCheck();
|
|
1632
1650
|
break;
|
|
1651
|
+
// Runs a 3-layer security audit independently of the pre-commit hook:
|
|
1652
|
+
// Layer 1 β npm audit (known CVEs in your dependencies)
|
|
1653
|
+
// Layer 2 β RetireJS (vulnerable JS libraries)
|
|
1654
|
+
// Layer 3 β Syft + Grype SBOM scan (if installed)
|
|
1655
|
+
// Run this periodically or in CI β not on every commit.
|
|
1656
|
+
// Usage: npx code-guard check-vuln
|
|
1633
1657
|
case 'check-vuln':
|
|
1634
1658
|
runVulnerabilityCheck();
|
|
1635
1659
|
break;
|
|
1660
|
+
// Generates (or re-opens) the last Code Guardian report in VS Code.
|
|
1661
|
+
// The report is a rich Markdown file at .code-guardian/CODE_GUARDIAN_REPORT.md
|
|
1662
|
+
// with violation details, solution examples, and quick-fix hints.
|
|
1663
|
+
// Usage: npx code-guard report
|
|
1636
1664
|
case 'report':
|
|
1637
1665
|
runReport();
|
|
1638
1666
|
break;
|
|
1667
|
+
// Auto-generates a feature documentation file for the current git branch.
|
|
1668
|
+
// Creates docs/features/<branch-name>.md with a structured template.
|
|
1669
|
+
// Encourages documenting every feature branch before merging.
|
|
1670
|
+
// Usage: npx code-guard doc
|
|
1639
1671
|
case 'doc':
|
|
1640
1672
|
generateDoc();
|
|
1641
1673
|
break;
|
|
1674
|
+
// Generates a PR checklist Markdown file based on all active rules.
|
|
1675
|
+
// Lists every rule the reviewer should manually verify.
|
|
1676
|
+
// Useful to paste into pull request descriptions.
|
|
1677
|
+
// Usage: npx code-guard checklist
|
|
1642
1678
|
case 'checklist':
|
|
1643
1679
|
generateChecklist();
|
|
1644
1680
|
break;
|
|
1681
|
+
// Validates the project's folder structure and file naming conventions
|
|
1682
|
+
// against the rules defined in:
|
|
1683
|
+
// .code-guardian/structure-rules.json
|
|
1684
|
+
// .code-guardian/naming-rules.json
|
|
1685
|
+
// Usage: npx code-guard validate
|
|
1645
1686
|
case 'validate':
|
|
1646
1687
|
runValidation();
|
|
1647
1688
|
break;
|
|
1689
|
+
// Removes all files and configurations that Code Guardian created.
|
|
1690
|
+
// Uses the manifest (.code-guardian/manifest.json) to know exactly
|
|
1691
|
+
// what was created vs modified β preserves your original content.
|
|
1692
|
+
// Also restores any backup files (e.g. .eslintrc.backup β .eslintrc).
|
|
1693
|
+
// Usage: npx code-guard uninstall [--yes]
|
|
1648
1694
|
case 'uninstall':
|
|
1649
1695
|
case 'cleanup':
|
|
1650
1696
|
await uninstallCodeGuard();
|
|
1651
1697
|
break;
|
|
1698
|
+
// Generates (or re-generates) an AI assistant config file for a specific tool.
|
|
1699
|
+
// Available assistants: cursor, copilot, claude, gemini, windsurf, junie,
|
|
1700
|
+
// antigravity, aider.
|
|
1701
|
+
// Also patches .gitignore so the generated file is tracked by git.
|
|
1702
|
+
// Usage: npx code-guard add-ai <name>
|
|
1703
|
+
// e.g. npx code-guard add-ai cursor
|
|
1652
1704
|
case 'add-ai':
|
|
1653
1705
|
addAI();
|
|
1654
1706
|
break;
|
|
1707
|
+
// Lists all available AI assistant integrations that Code Guardian can generate,
|
|
1708
|
+
// along with their target file paths and current status (exists / missing).
|
|
1709
|
+
// Usage: npx code-guard list-ai
|
|
1655
1710
|
case 'list-ai':
|
|
1656
1711
|
listAI();
|
|
1657
1712
|
break;
|
|
1713
|
+
// Prints the currently installed version of @hatem427/code-guard-ci.
|
|
1714
|
+
// Usage: npx code-guard version
|
|
1658
1715
|
case 'version':
|
|
1659
1716
|
case '--version':
|
|
1660
1717
|
case '-v':
|
|
1661
1718
|
showVersion();
|
|
1662
1719
|
break;
|
|
1720
|
+
// Displays full usage information: all commands, flags, and examples.
|
|
1721
|
+
// Usage: npx code-guard help
|
|
1663
1722
|
case 'help':
|
|
1664
1723
|
case '--help':
|
|
1665
1724
|
case '-h':
|