UNPKG

@aurelienbbn/agentlint

Version:

Stateless, deterministic CLI that bridges traditional linters and AI-assisted code review

185 lines (145 loc) 7.19 kB
--- name: agentlint/rule-advisor description: > Classify a code quality concern into the right enforcement tool and act on it. Activate when the user wants to enforce a pattern, catch a mistake, add a check, create a rule, prevent a practice, guard against regressions, set up linting, improve their feedback loop, or asks "how do I make sure X." type: core library: agentlint library_version: "0.1.5" sources: - "aurelienbobenrieth/agentlint:README.md" - "aurelienbobenrieth/agentlint:CONTRIBUTING.md" --- # Rule Advisor Classify what the user wants to enforce, pick the right tool, act on it. ## How to use this skill 1. Identify the specific pattern, practice, or constraint to enforce 2. If unclear, clarify with one targeted question 3. Check existing enforcement first: scan the project's lint rules, architecture tests, and agentlint config for overlap before creating anything new 4. Classify using the decision tree below 5. State your classification and reasoning in one sentence 6. For agentlint rules: implement using the template below. For other tools: guide the user to the right one ## Decision tree **Can a pattern be detected by looking at code structure (AST, file, imports)?** NO, and no metric or structure can trigger detection either → Document as a code review guideline. This is a team convention. YES, and the correct action is always the same (mechanical fix) → Existing linter rule (e.g. oxlint, eslint, biome, or similar) if a well-known rule exists for it. → Custom lint rule (e.g. eslint plugin, or similar) if it's project-specific but still deterministic. → Codemod (e.g. jscodeshift, ts-morph, or similar) if it needs automated rewriting across files. YES, but what to do about each finding requires judgment → **agentlint rule.** Deterministic detection, AI-evaluated action. **Is it about module or dependency structure?** → Dependency analysis (e.g. dependency-cruiser, madge, or similar) for import direction and boundaries. → CI check or agentlint rule for file/directory naming conventions. **Is it about runtime behavior?** → Type-level enforcement (e.g. branded types, schema validation, or similar) if it can be caught at compile time. → Tests (unit, integration, property-based) if it needs execution. → Monitoring if it needs production signals. ## Skills vs rules vs both Skills and agentlint rules serve different roles. A **skill** teaches the agent how to approach a domain — patterns, trade-offs, when to use what. A **rule** scans code after the fact and flags specific instances for evaluation. They are not mutually exclusive. **Skill alone** — the concern is about workflow, tooling usage, or cannot be detected by looking at code structure. Example: "use pnpm instead of npm" as a team preference, or "how to structure API routes." **Rule alone** — the pattern is self-contained and the rule's instruction provides enough context to evaluate each finding. Example: "flag TODO comments for triage." **Skill + rule together** — a skill teaches the broader philosophy, a rule enforces specific instances. The skill shapes how the agent writes code. The rule catches what slipped through. They reinforce each other. Example: a skill explains "use server actions for mutations, not API routes" with reasoning and patterns. A companion rule scans for API route files with POST handlers doing database writes, flagging them for evaluation against the skill's guidance. Use this pairing when a skill contains statements like "never do X", "always use Y", or "avoid Z pattern" and the pattern is AST-detectable. ### When to extract rules from skills Review existing skills for statements like "never do X", "always use Y", or "avoid Z pattern." If the pattern is AST-detectable, extract it into an agentlint rule. Keep the skill for the broader guidance and reasoning, move the specific enforcement to the rule. This gives you: - **Coverage** — the rule catches every instance, not just when the agent happens to recall the skill - **Auditability** — flagged patterns are visible in agentlint output - **Separation** — the skill teaches, the rule verifies ## When the answer is agentlint agentlint's niche: deterministic detection + non-deterministic evaluation. Three scopes are available: - **Single-node visitor** - flag individual AST nodes (comments, functions, catch blocks, magic numbers) - **Program visitor** - analyze the full file AST (duplicate function bodies, nested loops, export counts, prop counts) - **File-level targeting** - use include/ignore globs to scope rules to specific directories or file patterns ### Rule template ```typescript import { defineRule } from "@aurelienbbn/agentlint"; const myRule = defineRule({ meta: { name: "rule-name", description: "One-line description of what this detects", languages: ["ts", "tsx"], include: ["src/**"], // optional: scope to paths ignore: ["**/*.test.*"], // optional: exclude paths instruction: `[Be specific. Tell the AI agent exactly what to evaluate for each finding, when a finding is acceptable, and what action to take when it is a true positive.]`, }, createOnce(context) { return { // Available visitors: program, function_declaration, arrow_function, // call_expression, identifier, string, comment, class_declaration, // method_definition, property_identifier, type_annotation, // interface_declaration, import_statement, export_statement, // variable_declarator, if_statement, return_statement, // object, array, pair, jsx_element, jsx_self_closing_element comment(node) { context.flag({ node, message: node.text.trim() }); }, }; }, }); ``` ### AgentReviewNode API - `text` - source text of the node - `type` - tree-sitter node type - `startPosition` / `endPosition` - `{ row, column }` - `children` - child nodes array - `parent` - parent node or undefined - `child(i)` / `namedChild(i)` - get child by index - `childForFieldName(name)` - get child by field name - `descendantsOfType(type)` - find all descendants matching a type ### Writing good instructions The instruction determines whether findings are actionable or noise. A good instruction has three parts: what to evaluate, what's acceptable, and what action to take on true positives. Bad: "Review this code" Good: "Evaluate each flagged catch block. If the error is logged and re-thrown, it is acceptable. If the error is silently swallowed - empty catch or catch with only a console.log - suggest adding proper error handling or propagation." The agent reads only the instruction, not the rule source. If the instruction is vague, every finding becomes noise. If it over-specifies, acceptable patterns get flagged as issues. ### Testing ```bash <agentlint-cmd> check --all --rule rule-name <agentlint-cmd> check src/handlers/checkout.ts --rule rule-name <agentlint-cmd> check --all --rule rule-name --dry-run ``` Resolve `<agentlint-cmd>` from the repo's package manager before running these commands: - npm: `npm exec agentlint --` - pnpm: `pnpm agentlint` - yarn: `yarn agentlint` - bun: `bun run agentlint`