Install
$ agentstack add skill-bensheridanedwards-architectplaybook-linting-audit ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
/linting-audit
Audit a TypeScript project's lint configuration against an opinionated baseline organised in four layers — configuration shape, rule coverage, strictness and enforcement, suppressions hygiene — preceded by a diagnostic snapshot. Then offer to generate an implementation plan for the gaps.
The default mental model is TypeScript and React. The skill auto-detects and supports both ESLint (with the modern flat configuration format) and Biome. It audits the linter actually in use; dual-installation is itself a Layer 1 violation.
How this differs from /quality-gates-audit
/quality-gates-audit checks whether linting runs in pre-commit, pre-push, and continuous integration — that's a lifecycle question. /linting-audit checks whether the linting itself is well-configured — coverage, strictness, suppressions hygiene. They complement; they do not duplicate. A project can pass quality-gates-audit (the linter runs at every stage) and still fail linting-audit (the linter is misconfigured to ignore most things), and vice versa.
Static-first design with optional run enrichment
This skill is read-only. ESLint and Biome are themselves read-only when invoked for linting (no side effects, no file changes), so opting into a real run is safe — just slow on large codebases. Two modes:
- Static (default). Read the lint configuration files,
package.json, source files (for suppression detection), and continuous-integration workflow files. Counts and rule-coverage analysis are based on configuration shape; suppressions are counted from comment text. - Static plus opt-in
--with-run. Additionally invoke the project's lint command in JSON-reporter mode (eslint . --format json, orbiome lint --reporter json), capture the output, and use the actual warnings and errors to enrich the diagnostic snapshot and a small number of run-required checks.
The skill never invokes any linter with --fix or any other mutating flag. Running with --fix is the user's job (or a separate fix skill); keeping this audit fully read-only is what makes it safe to run in any working tree at any time.
Usage
/linting-audit # default: concise Top 5 + full report saved + ask about plan
/linting-audit --worktree # create an isolated Git worktree, then run the audit there
/linting-audit --learn # mid-level engineer teaching mode (detailed explanations + file/line examples)
/linting-audit --teach # alias for --learn
/linting-audit --with-run # static plus enrichment from a real lint run
/linting-audit --threshold-suppressions-per-file=10 # override default 5
💡 Pro tip: Add --worktree to run this audit in an isolated Git worktree.
The skill never accepts --apply. The implementation plan is descriptive Markdown.
💡 Pro tip: Run /preflight --audit=linting first to detect — and optionally install — the development dependency that makes --with-run useful (eslint or @biomejs/biome, depending on which linter your project uses). Skip if you already know the tooling is wired up.
The opinionated baseline
A check resolves to one of four statuses:
- present — the invariant holds.
- partial — most signals resolve, with a small number of exceptions, or the codebase shows mixed adherence to a soft check.
- missing — a structural prerequisite is absent (no linter installed, for example).
- violation — the audit identified concrete configuration that breaks the invariant.
Layer 0 is informational only and has no status.
Layer 0 — Diagnostic snapshot (always written, no pass/fail)
- Detected linter and version (ESLint 9.x, Biome 1.x, or none).
- Configuration files and their format (flat config
eslint.config.{js,ts,mjs}, legacy.eslintrc.*,biome.json/biome.jsonc). - Approximate enabled-rule count: sum of rules introduced by
extendsplus rules explicitly set in the configuration. - Source-file count in scope, post-ignore patterns.
- Total suppression count:
eslint-disable*andbiome-ignorecomments across the codebase. - Top 10 most-suppressed rules. Sourced from the actual lint output when running with
--with-run; otherwise inferred by parsing the rule names from suppression comments. - Top 10 files with the most suppressions, with their suppression count.
- Total warnings and errors from the actual lint run (only when
--with-run).
Layer 1 — Configuration shape
| Check | Expectation | Violation signal | | --- | --- | --- | | Exactly one linter installed | Either ESLint or Biome, not both. | Both eslint and @biomejs/biome present in package.json dependencies. | | Modern configuration format | ESLint uses flat config (eslint.config.{js,ts,mjs}); Biome uses biome.json or biome.jsonc. | ESLint legacy format (.eslintrc.*) in use, deprecated as of ESLint 9. | | Single configuration source | Exactly one configuration file at the repository root (or workspace package root). | Multiple top-level configuration files, or both flat and legacy formats present simultaneously. | | TypeScript parser configured (ESLint only) | The configuration registers @typescript-eslint/parser and either parserOptions.project or parserOptions.projectService so type-aware rules can run. Biome's TypeScript support is implicit. | ESLint configuration without a TypeScript parser despite tsconfig.json being present. | | Declarative configuration | The configuration does not require side-effectful evaluation: no environment-dependent rule selection, no asynchronous configuration loaders. Soft check — reported as partial. | Configuration that branches on process.env in non-trivial ways. |
Layer 2 — Rule coverage
The audit dispatches based on the detected linter. Whichever path runs, every check below is scoped to that linter.
When ESLint is detected
| Check | Expectation | Violation signal | | --- | --- | --- | | Base recommended set extended | The base recommended ruleset is extended (in flat config: js.configs.recommended from @eslint/js; in legacy: eslint:recommended). | No base ruleset extended. | | @typescript-eslint recommended-type-checked or stronger | At least recommended-type-checked is extended; strict-type-checked is preferred. The plain recommended set is reported as partial because it skips the type-aware rules. | No @typescript-eslint configuration; or recommended only (reported as partial). | | eslint-plugin-react/recommended (React only) | When React is detected, the React recommended config is extended. | React project without the plugin configured. | | eslint-plugin-react-hooks/recommended (React only) | When React is detected, the hooks plugin's recommended rules are enabled. | React project without it. | | eslint-plugin-jsx-a11y/recommended (React only) | When React is detected, the accessibility plugin's recommended rules are enabled. (Surfaces the gap here as well as in /accessibility-audit, so a single fix passes both.) | React project without it. | | eslint-plugin-import configured | The import plugin is configured with the TypeScript resolver (eslint-import-resolver-typescript) plus rules for unresolved imports, import order, and no-cycle. | Plugin missing, or installed without the TypeScript resolver. | | eslint-config-prettier last in extends | When Prettier is in the project, eslint-config-prettier is the last entry in the extends list so it disables formatting rules that would conflict with Prettier. | Prettier installed but config not added; or added but not last. | | Node best-practices plugin | When the project has Node-only entry points (server code, build scripts), eslint-plugin-n's recommended rules are enabled. Skipped silently for browser-only frontends. | Node entry points present without the plugin. |
When Biome is detected
| Check | Expectation | Violation signal | | --- | --- | --- | | Linter enabled | linter.enabled is true in biome.json. | Linter disabled. | | Recommended rules enabled | linter.rules.recommended is true. | Recommended rules off. | | Domain rule sets enabled | Each of correctness, suspicious, complexity, performance, security, style, plus a11y (when React detected) has recommended: true, or rule-by-rule coverage of equivalent strength. | Any of the above set off without rule-by-rule replacement. | | Type-aware rules enabled | The configuration does not opt out of TypeScript-specific rules. | javascript.parser.disabled or analogues set in a way that disables TypeScript-aware checks. |
Layer 3 — Strictness and enforcement
| Check | Expectation | Violation signal | | --- | --- | --- | | Lint script in package.json | A lint script exists and invokes the detected linter against the project. | No lint script, or the script invokes a different tool. | | Continuous integration enforces zero warnings | The continuous-integration lint step uses --max-warnings=0 for ESLint, or --error-on-warnings for Biome. | Workflow runs lint without the zero-warnings flag, or lint failures don't fail the build. | | Type-aware rules actually enabled (ESLint only) | When @typescript-eslint/parser is configured, parserOptions.project (or the flat-config parserOptions.projectService) is set so type-aware rules can run. | Parser configured but the project pointer is missing — type-aware rules silently no-op. | | No globally disabled rules without justification | The configuration does not turn off rules from extended recommended sets globally without an inline comment explaining why. | A rule overridden to 'off' (or 0) at the top level of the configuration without a comment. | | Lint errors fail the build | Continuous integration treats lint errors as build failures: no || true, no continue-on-error: true on the lint step. | Workflow patterns that swallow lint failures. | | Editor integration available | A workspace-level recommendation exists for the linter's editor extension (.vscode/extensions.json for VS Code, equivalent for other editors), so the linter runs locally in the same configuration as continuous integration. Soft check — reported as partial. | No editor-recommendation configuration. |
Layer 4 — Suppressions hygiene
| Check | Expectation | Violation signal | | --- | --- | --- | | No blanket file-level disables without justification | /* eslint-disable */ (no rule list) at the top of a file is reported as violation unless the same line (or the line above) carries a free-text justification. Equivalent: // biome-ignore-all at the top of a file in Biome. | Blanket disable with no following justification. | | Each disable specifies rules | eslint-disable-next-line and inline disable comments specify which rules they disable, never blanket. Same expectation for Biome's biome-ignore comments. | Bare eslint-disable-next-line (or analogous) with no rule names. | | Each suppression carries a justification | Every suppression comment is followed by free-text justification (on the same line or the line above). Soft check — reported as partial when adherence is mixed. | Suppression comments with no surrounding explanation. | | ignores/.eslintignore does not exclude production source | The ignore patterns do not exclude entire production source directories, individual feature folders, or *.ts/*.tsx blanketly. | Patterns that ignore production code under src/ (or the framework equivalent). | | No stale ignore entries | Every entry in the ignore list resolves to at least one existing file or directory. | Entries pointing at paths that no longer exist. | | Suppression density is reasonable | Files contain at most the threshold suppressions each (default 5; tunable via --threshold-suppressions-per-file). Soft check — reported as partial above the threshold. | Files exceeding the threshold. |
What this skill does
- Reads the knowledge graph when present. Soft dependency: when
graphify-out/graph.jsonexists, the implementation plan can rank suppression-heavy files by graph centrality — a suppression in a god node is more consequential than one in a leaf utility, and the plan recommends those for cleanup first. The audit still runs in full when the graph is absent. - Confirms a TypeScript project. Detects
package.json,tsconfig.json, and a TypeScript dependency. If absent, the skill stops and tells the user it currently supports TypeScript projects only. - Detects the linter. Looks for
eslintand/or@biomejs/biomeinpackage.jsondependencies, then for the configuration files of each. When neither is detected, the audit stops with a clear message: a project with no linter is a/quality-gates-auditproblem first. - Detects React for the React-conditional rule-coverage checks.
- When
--with-runis set, invokes the detected linter in JSON-reporter mode, captures the output, and parses it. If the lint command fails to start (binary missing, configuration syntactically invalid), records the failure and degrades run-dependent checks topartial. - Writes Layer 0 — the diagnostic snapshot to
.architect-audits/linting-audit/snapshot.mdand prepends the same content tofindings.md. - Walks each check in the active layer list, dispatching to the ESLint or Biome variant where the layer 2 checks differ. Records a status, evidence, and (where relevant) sample file references per check.
- Writes phase 1 outputs to
.architect-audits/linting-audit/:
findings.md— diagnostic snapshot followed by check results, grouped by layer.findings.json— machine-readable.snapshot.md— diagnostic snapshot on its own.metadata.json— skill version, run timestamp, Graphify revision (when present), detected linter and version, React-detected flag, applied thresholds, applied filters, run output presence.
- Phase 2 — offers to plan the gaps. Summarises the findings in chat and asks the user a single yes-or-no question:
> "Generate an implementation plan for the linting gaps? (yes/no)"
On yes, writes .architect-audits/linting-audit/implementation-plan.md describing exactly which configuration entries to add or change, which plugins to install, which suppressions to clean up first (graph-prioritised when the graph is present), and which continuous-integration steps to tighten — ordered by layer. The plan does not modify any project files.
On no, exits cleanly.
Implementation steps
Step 1 — Confirm the prerequisites
test -f package.json || { echo "linting-audit: no package.json detected. This skill currently supports TypeScript projects only."; exit 1; }
test -f tsconfig.json || { echo "linting-audit: no tsconfig.json detected. This skill currently supports TypeScript projects only."; exit 1; }
Step 2 — Detect the linter
Read package.json dependencies:
eslintpresent → ESLint path.@biomejs/biomepresent → Biome path.- Both present → record both, run the appropriate path for whichever is configured (presence of
eslint.config.*/.eslintrc.*vsbiome.json), and surface the dual-installation as aviolationon the layer 1 "exactly one linter installed" check. - Neither present → stop with a clear message:
> linting-audit requires a linter (ESLint or Biome). No linter detected. Install one and configure it before running this audit; /quality-gates-audit will surface the gap as well.
Step 3 — Detect React
Look for react in dependencies (directly or via Next.js, Remix, etc.). Determines whether the React-specific rule-coverage checks run.
Step 4 — Optionally run the linter
When --with-run is set, invoke the detected linter:
- ESLint:
npx eslint . --format json(capture stdout, parse JSON). - Biome:
npx biome lint --reporter json .(capture stdout, parse JSON).
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: BenSheridanEdwards
- Source: BenSheridanEdwards/ArchitectPlaybook
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.