eslint-plugin-ai-guard 1.1.11 โ 1.1.12
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 +23 -0
- package/dist/cli/index.js +71 -16
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -57,6 +57,29 @@ This writes:
|
|
|
57
57
|
Your AI tools will now avoid these patterns before you even run the linter.
|
|
58
58
|
Use `--force` to regenerate after upgrading to a new version with new rules.
|
|
59
59
|
|
|
60
|
+
## ๐ค Set Up AI Agent Rules
|
|
61
|
+
|
|
62
|
+
Generate instruction files so Claude Code, Cursor, and GitHub Copilot
|
|
63
|
+
automatically avoid the 17 most common AI-generated anti-patterns:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npx ai-guard init-context
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Follow the prompts to select your agent(s). Or generate all at once:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npx ai-guard init-context --all
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
This writes:
|
|
76
|
+
- `CLAUDE.md` โ read automatically by Claude Code
|
|
77
|
+
- `.cursorrules` โ read automatically by Cursor
|
|
78
|
+
- `.github/copilot-instructions.md` โ read automatically by GitHub Copilot
|
|
79
|
+
|
|
80
|
+
Your AI tools will now avoid these patterns before you even run the linter.
|
|
81
|
+
Use `--force` to regenerate after upgrading to a new version with new rules.
|
|
82
|
+
|
|
60
83
|
## ๐งช Real-World Usage Philosophy
|
|
61
84
|
|
|
62
85
|
`ai-guard` is designed for production adoption in existing codebases:
|
package/dist/cli/index.js
CHANGED
|
@@ -1772,6 +1772,30 @@ var SECTION_MAP = {
|
|
|
1772
1772
|
function getSections(categories) {
|
|
1773
1773
|
return categories.map((cat) => SECTION_MAP[cat]()).join("\n\n");
|
|
1774
1774
|
}
|
|
1775
|
+
function workflowGuidanceMarkdown() {
|
|
1776
|
+
return `## Workflow Guardrails
|
|
1777
|
+
- Follow user and repository instructions first; apply these rules on top.
|
|
1778
|
+
- Reuse existing project patterns and libraries before introducing new abstractions.
|
|
1779
|
+
- If a rule must be bypassed intentionally, add a suppression comment with reason:
|
|
1780
|
+
\`ai-guard-disable <rule-name> -- reason: <why>\`.
|
|
1781
|
+
- Before finalizing changes, run tests/lint and \`ai-guard run\` when available.`;
|
|
1782
|
+
}
|
|
1783
|
+
function workflowGuidanceCursor() {
|
|
1784
|
+
return `## Workflow Guardrails
|
|
1785
|
+
|
|
1786
|
+
- Follow user and repository instructions first.
|
|
1787
|
+
- Prefer existing project patterns and dependencies.
|
|
1788
|
+
- If bypassing a rule intentionally, add: ai-guard-disable <rule-name> -- reason: <why>.
|
|
1789
|
+
- Validate generated code with tests/lint and ai-guard run when available.`;
|
|
1790
|
+
}
|
|
1791
|
+
function workflowGuidanceCopilot() {
|
|
1792
|
+
return `## Required Workflow
|
|
1793
|
+
|
|
1794
|
+
- Follow user and repository instructions first.
|
|
1795
|
+
- Prefer edits that match existing architecture and dependencies.
|
|
1796
|
+
- If intentionally violating an ai-guard rule, add an inline suppression with a reason.
|
|
1797
|
+
- Run tests/lint and \`ai-guard run\` before finalizing changes when possible.`;
|
|
1798
|
+
}
|
|
1775
1799
|
function generateClaudeFile(version, categories) {
|
|
1776
1800
|
return `<!-- DO NOT EDIT MANUALLY \u2014 generated by eslint-plugin-ai-guard -->
|
|
1777
1801
|
<!-- Regenerate: npx ai-guard init-context --force -->
|
|
@@ -1781,6 +1805,8 @@ function generateClaudeFile(version, categories) {
|
|
|
1781
1805
|
You are coding in a project that uses eslint-plugin-ai-guard.
|
|
1782
1806
|
Avoid generating the following patterns. They will be flagged as lint errors.
|
|
1783
1807
|
|
|
1808
|
+
${workflowGuidanceMarkdown()}
|
|
1809
|
+
|
|
1784
1810
|
${getSections(categories)}
|
|
1785
1811
|
|
|
1786
1812
|
---
|
|
@@ -1877,6 +1903,8 @@ anti-patterns generated by AI coding tools. Follow these rules when
|
|
|
1877
1903
|
generating or editing code in this project. Violations will be flagged
|
|
1878
1904
|
as lint errors.
|
|
1879
1905
|
|
|
1906
|
+
${workflowGuidanceCursor()}
|
|
1907
|
+
|
|
1880
1908
|
${sections}
|
|
1881
1909
|
|
|
1882
1910
|
---
|
|
@@ -1978,6 +2006,8 @@ function generateCopilotFile(version, categories) {
|
|
|
1978
2006
|
This project uses \`eslint-plugin-ai-guard\`. Follow these rules to avoid
|
|
1979
2007
|
generating patterns that will be flagged as lint errors.
|
|
1980
2008
|
|
|
2009
|
+
${workflowGuidanceCopilot()}
|
|
2010
|
+
|
|
1981
2011
|
## Quick Reference
|
|
1982
2012
|
|
|
1983
2013
|
${copilotQuickRef(categories)}
|
|
@@ -2041,10 +2071,19 @@ function parseCategories(raw) {
|
|
|
2041
2071
|
}
|
|
2042
2072
|
return valid.length > 0 ? valid : ALL_CATEGORIES;
|
|
2043
2073
|
}
|
|
2074
|
+
function normalizeSelectedAgents(raw) {
|
|
2075
|
+
if (Array.isArray(raw)) {
|
|
2076
|
+
return raw.filter((value) => typeof value === "string");
|
|
2077
|
+
}
|
|
2078
|
+
if (typeof raw === "string") {
|
|
2079
|
+
return [raw];
|
|
2080
|
+
}
|
|
2081
|
+
return [];
|
|
2082
|
+
}
|
|
2044
2083
|
function registerInitContextCommand(program2) {
|
|
2045
2084
|
program2.command("init-context").description(
|
|
2046
2085
|
"Generate AI agent instruction files (CLAUDE.md, .cursorrules, copilot-instructions.md)\nso Claude Code, Cursor, and GitHub Copilot avoid the 17 most common AI anti-patterns."
|
|
2047
|
-
).option("--all", "Generate files for all agents (skip prompt)").option("--force", "Overwrite existing files without asking").option("--dry-run", "Print what would be generated without writing files").option("--rules <categories>", "Comma-separated categories: async,security,error-handling,quality").action(async (opts) => {
|
|
2086
|
+
).option("-a, --all", "Generate files for all agents (skip prompt)").option("--force", "Overwrite existing files without asking").option("--dry-run", "Print what would be generated without writing files").option("--rules <categories>", "Comma-separated categories: async,security,error-handling,quality").action(async (opts) => {
|
|
2048
2087
|
const cwd = process.cwd();
|
|
2049
2088
|
const version = getPackageVersion2(cwd);
|
|
2050
2089
|
const categories = parseCategories(opts.rules);
|
|
@@ -2059,23 +2098,39 @@ function registerInitContextCommand(program2) {
|
|
|
2059
2098
|
if (opts.all) {
|
|
2060
2099
|
selectedAgents = [...AGENTS];
|
|
2061
2100
|
} else {
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2101
|
+
let wasCancelled = false;
|
|
2102
|
+
const response = await (0, import_prompts2.default)(
|
|
2103
|
+
{
|
|
2104
|
+
type: "multiselect",
|
|
2105
|
+
name: "agents",
|
|
2106
|
+
message: "Which AI agents do you use?",
|
|
2107
|
+
choices: [
|
|
2108
|
+
{ title: "Claude Code", value: "claude", description: "\u2192 writes CLAUDE.md" },
|
|
2109
|
+
{ title: "Cursor", value: "cursor", description: "\u2192 writes .cursorrules" },
|
|
2110
|
+
{ title: "GitHub Copilot", value: "copilot", description: "\u2192 writes .github/copilot-instructions.md" },
|
|
2111
|
+
{ title: "All three (recommended)", value: "all", description: "\u2192 writes all files" }
|
|
2112
|
+
],
|
|
2113
|
+
hint: "Space: select | Enter: confirm",
|
|
2114
|
+
instructions: true,
|
|
2115
|
+
min: 1,
|
|
2116
|
+
warn: "Select at least one agent."
|
|
2117
|
+
},
|
|
2118
|
+
{
|
|
2119
|
+
onCancel: () => {
|
|
2120
|
+
wasCancelled = true;
|
|
2121
|
+
return false;
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
);
|
|
2125
|
+
if (wasCancelled) {
|
|
2126
|
+
log.info("Selection cancelled. Nothing to do.");
|
|
2127
|
+
return;
|
|
2128
|
+
}
|
|
2129
|
+
const selected = normalizeSelectedAgents(response.agents);
|
|
2130
|
+
if (selected.length === 0) {
|
|
2131
|
+
log.info("No valid agents selected. Use --all to generate all files.");
|
|
2076
2132
|
return;
|
|
2077
2133
|
}
|
|
2078
|
-
const selected = response.agents;
|
|
2079
2134
|
if (selected.includes("all")) {
|
|
2080
2135
|
selectedAgents = [...AGENTS];
|
|
2081
2136
|
} else {
|