From vigiles
Upgrades guidance() rules in .spec.ts files to enforce() using matching rules from installed linters like ESLint and Ruff, via Vigiles generated types. Ideal for hardening specs with real linting.
npx claudepluginhub zernie/vigilesThis skill uses the workspace's default tool permissions.
Scan spec files for `guidance()` rules and suggest `enforce()` replacements backed by real linter rules.
Lints coding agent instruction files (CLAUDE.md, .cursorrules, AGENTS.md) for vagueness, conflicts, redundancies, ordering issues, misplaced rules, weak emphasis, and token budget. Provides ratings, gap detection, and consolidations.
Sets up ast-grep in TypeScript codebases with rules detecting anti-patterns, enforcing best practices, and preventing bugs. Creates sgconfig.yml, rule files, and tests for structural linting, legacy bans, and ratchet gates.
Automates format-lint-resolve pipelines for code editing tasks. Discovers linters from pyproject.toml/.pre-commit-config.yaml/package.json, fixes ruff/mypy/bandit issues, ensures quality before completion.
Share bugs, ideas, or general feedback.
Scan spec files for guidance() rules and suggest enforce() replacements backed by real linter rules.
Ask the user:
Auto or interactive?
- Auto — I'll apply all safe changes (direct replacements where the rule is already enabled), commit, and show you the diff. Risky changes (require config edits or plugin installs) go in a summary for you to review.
- Interactive — I'll present each suggestion and you pick which ones to apply.
Default to interactive if the user doesn't specify.
Run npx vigiles generate-types to get the full list of enabled linter rules in the project. Read .vigiles/generated.d.ts to see every rule available across all detected linters.
Note which linter prefixes appear in the generated types (e.g., EslintRule, RuffRule). You'll only need reference docs for detected linters.
Find all .spec.ts files in the project (**/*.md.spec.ts). For each file, identify every guidance() rule.
For each guidance rule, check if an enabled rule in .vigiles/generated.d.ts directly matches. This is the fast, deterministic path — no doc reading needed.
Look for:
no-console is in EslintRuleno-console is availableno-unused-vars or @typescript-eslint/no-unused-vars is availableIf a match is found and the rule is in the generated types (meaning it's already enabled), this is a direct replacement — no config changes needed.
For guidance rules that didn't match in Step 3, read the linter reference docs for the project's detected linters:
../linter-docs/eslint.md../linter-docs/stylelint.md../linter-docs/ruff.md../linter-docs/pylint.md../linter-docs/rubocop.md../linter-docs/clippy.mdOnly read docs for linters the project actually uses. Skip docs for linters with no rules in generated types.
Check the plugin tables and decision matrices. The guidance text may describe a pattern covered by:
no-restricted-* config pattern (see Step 4b)no-restricted-* PatternsMany guidance rules can be enforced via built-in linter config without a custom rule. This is the most common strengthen pattern — "don't do X" maps to a restriction config.
ESLint:
// "Don't import from internal modules"
"no-restricted-imports": ["error", {
patterns: [{ group: ["src/internal/*"], message: "Use the public API." }]
}],
// "Don't call console.log"
"no-restricted-syntax": ["error", {
selector: 'CallExpression[callee.object.name="console"]',
message: "Use the project logger."
}],
// "Don't use moment.js"
"no-restricted-imports": ["error", {
paths: [{ name: "moment", message: "Use dayjs instead." }]
}],
Ruff:
# "Don't use os.system"
[tool.ruff.lint.flake8-tidy-imports.banned-api]
"os.system".msg = "Use subprocess.run instead."
RuboCop:
# "Don't use puts in production" — if Rails/Output doesn't fit
Custom/NoPuts:
Enabled: true
When suggesting a no-restricted-* change:
enforce() rule that references itGroup the output into tiers:
Tier 1: Direct replacements (rule already enabled — zero risk)
// Before
"no-console": guidance("Use structured logger instead of console.log"),
// After
"no-console": enforce("eslint/no-console", "Use structured logger instead of console.log"),
Tier 2: Config-backed (rule exists but needs config options)
// Spec change:
"no-moment": enforce("eslint/no-restricted-imports", "Use dayjs instead of moment."),
// Config change needed (eslint.config.mjs):
"no-restricted-imports": ["error", {
paths: [{ name: "moment", message: "Use dayjs instead." }]
}],
Tier 3: Plugin install needed
"cognitive-complexity": guidance("Keep functions simple")
→ Install eslint-plugin-sonarjs, enable sonarjs/cognitive-complexity
→ enforce("eslint/sonarjs/cognitive-complexity", "Keep functions simple")
Tier 4: No match (stays as guidance, or candidate for /pr-to-lint-rule)
"research-first": guidance("Google unfamiliar APIs first.")
→ No linter rule can enforce this. Stays as guidance.
→ Want me to run /pr-to-lint-rule to create a custom rule?
In auto mode:
guidance() with enforce())npm run build && npx vigiles compile to verify each change compilesIn interactive mode:
npm run build && npx vigiles compile to verifyFor Tier 4 (no match): Ask the user if they want to run /pr-to-lint-rule for any of the unmatched rules to create custom rules.