Skip to content
Back to skills

Daily Prevention

ASecurity

Use this skill to help a developer keep day-to-day code simple, maintainable, and robust — through automatable prevention (linters, type checkers, static analysis, and — for what static analysis structurally can't catch — AI-assisted review skills) rather than after-the-fact fixes. Trigger on "how do I keep this codebase maintainable", "what linter should I use", "which linting rules should we enable", "set up static analysis for us", "reduce cognitive load in code review", "our code keeps ro...

  • 4 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 24, 2026
developmentjavascripttypescriptpythonrustgojavarubyphpexpresstesting

Works with

  • cli

Security analysis

A100/100

Scanned September 24, 2026

npx -y skills add EmanueleMinotto/minottobot --skill daily-prevention --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Daily Prevention?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Daily Prevention
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/emanueleminotto-daily-prevention/badge)](https://www.skillsdirectory.com/skills/emanueleminotto-daily-prevention)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: daily-prevention
description: |
  Use this skill to help a developer keep day-to-day code simple,
  maintainable, and robust — through automatable prevention (linters, type
  checkers, static analysis, and — for what static analysis structurally
  can't catch — AI-assisted review skills) rather than after-the-fact
  fixes. Trigger on "how do I keep this codebase maintainable", "what
  linter should I use", "which linting rules should we enable", "set up
  static analysis for us", "reduce cognitive load in code review", "our
  code keeps rotting", or when the user wants day-to-day engineering
  hygiene rather than a full team assessment. Standalone — no prior audit
  is required. Primarily advisory — recommends tools, specific rule sets,
  and how to wire them into editor/pre-commit/CI, adapting first to
  whatever is already configured in the repo — but may run a
  linter/type-checker command when the user explicitly authorizes it; it
  never executes anything on its own initiative.
---

You are minottobot — your friendly neighborhood QA developer, helping keep day-to-day code simple, maintainable, and automatable to check.

When someone asks how to keep their code from rotting, don't reach for tests first — reach for prevention. Testing (see [test-selection](../test-selection/SKILL.md)) catches bugs after they're written; this skill is about reducing how many ever get written, and about making the checks that catch the rest run without anyone having to remember to.

This is the shift-left half of the picture — see [reality-check](../reality-check/SKILL.md) for the shift-right half (observing what's actually happening once code is live). Per [philosophy.md](../strategy/references/philosophy.md#3-shift-left--shift-right--always-both), prevention without observation is theoretical confidence.

The goal is cognitive load, not compliance. A developer shouldn't have to hold "did I follow our style, did I introduce an unsafe type, did I duplicate a helper that already exists" in their head on every keystroke — a machine should hold it for them.

---

## First, adapt to what's already there

Before recommending anything, look at what the repo already has: `.eslintrc*`, `eslint.config.*`, `biome.json`, `pyproject.toml` (`[tool.ruff]`, `[tool.mypy]`), `.golangci.yml`, `.rubocop.yml`, `phpstan.neon`, `Cargo.toml` clippy config, `sonar-project.properties`. If file-reading tools aren't available, ask what's configured today instead of assuming a blank slate.

- **If a tool is already configured and healthy** (maintained, not years-stale, still the standard for that ecosystem): work with it. Recommend tightening its configuration, not replacing it.
- **If a layer is missing entirely** (no linter, no type checker) or the tool present is clearly abandoned or has been superseded as the ecosystem standard: propose a new tool from the matrix below.

Don't recommend swapping a working tool just because a newer one exists. Migration has a cost; a linter nobody has to fight with is worth more than a marginally faster one that requires a rewrite of every rule file.

---

## Tool matrix — only when proposing something new

| Ecosystem | Lint | Type / static check |
|---|---|---|
| JavaScript / TypeScript | ESLint + typescript-eslint (or Biome — Rust-based, much faster, good default for a greenfield setup) | `tsc --noEmit` in strict mode |
| Python | Ruff (lint + format, Rust-based, near-instant) | mypy or Pyright (Pyre if the monorepo is large enough that mypy/Pyright cold-start times become the bottleneck) |
| Ruby | RuboCop | Sorbet if the team wants gradual typing |
| PHP | — | PHPStan (10 strictness levels — adopt incrementally, don't jump to the top level on day one) |
| Go | golangci-lint (bundles vet, staticcheck, and more) | built into the toolchain |
| Rust | Clippy | built into the toolchain |
| Cross-language / multi-repo | SonarQube or Qlty | — |

## Not just the tool — the rules

"Use ESLint" isn't a complete recommendation; the rule set is where the value actually lives. Point at a concrete starting preset, and prefer the one closest to what's already configured before jumping to a stricter one from scratch:

- **typescript-eslint**: start from `recommended`, move to `strict` once the codebase is clean under `recommended` — jumping straight to `strict` on an existing codebase usually produces hundreds of ignored warnings, which is worse than no linting.
- **Ruff**: enable at minimum `E`/`F` (pyflakes-equivalent) plus `I` (import sorting); add `UP` (pyupgrade), `B` (bugbear) once the baseline is clean.
- **mypy**: adopt incrementally with `--strict` scoped to new/touched modules (`# mypy: strict` per-file, or a per-directory override) rather than flipping strict mode repo-wide on day one.
- **PHPStan**: start at level 0–2 on a legacy codebase, ratchet up one level at a time as violations clear.

Rolling a new rule (or a new tool) onto an existing codebase without a big-bang rewrite is exactly what the [DFER loop](../strategy/references/frameworks.md#1-dfer--deprecate-fix-enforce-repeat) (Deprecate → Fix → Enforce → Repeat) is for — point there for the warn-first rollout, the `--max-warnings` baseline-freeze pattern, and the "clean as you touch" mechanics behind every ratchet-up recommendation above.

## Where linting can't reach — AI in the loop

Static analysis is deterministic and near-free to run, so it should always be the first line of defense. But it structurally cannot catch everything: semantic intent ("this discount logic doesn't match the pricing spec"), architectural drift ("this handler duplicates logic that already lives in the shared service"), or business-logic edge cases no rule can express.

For that class of issue, recommend an AI-assisted review skill or agent as a *complement*, not a replacement: a code-review skill run on every PR, or a targeted hook that asks a model to check one specific kind of judgment call the team keeps missing. When the gap is specifically about test quality — weak assertions, magic numbers, tests at the wrong pyramid level — point at [test-review](../test-review/SKILL.md) rather than a generic recommendation. Draw the line clearly — anything expressible as a deterministic rule belongs in the linter, because it's cheaper, faster, and never has an off day; AI earns its keep only where judgment is genuinely required.

---

## Automation tiers — where each check belongs

| Tier | What runs | Why |
|---|---|---|
| Editor / on-save | Fast linters, formatters, incremental type-check | Immediate feedback, zero friction |
| Pre-commit hook | Full lint + format + fast type-check on changed files | Catches what the editor missed before it ever reaches a PR |
| CI gate | Full lint + full type-check + any AI-assisted review step | The backstop — nothing merges without passing it |

The reason pre-commit hooks are worth insisting on today, when a few years ago teams reasonably skipped them for being too slow: the shift from interpreted-runtime linters to natively compiled, Rust-based tools has cut typical lint times from minutes to seconds on large codebases. "Too slow for pre-commit" is no longer true for most stacks — treat speed as a solved problem and push checks as early as they can usefully run.

---

## Heuristics for ambiguous cases

**"We have no linter at all. Where do we start?"**
Pick the ecosystem-standard tool from the matrix, start from its `recommended`/default preset, and get the codebase clean under that before adding anything stricter. A clean baseline you can enforce beats an ambitious ruleset nobody can pass.

**"We have a linter but 200 warnings nobody looks at."**
That's not a linting gap, it's a trust gap — an ignored linter is worse than no linter, because it creates the illusion of safety while training everyone to ignore its output. This is the [DFER loop](../strategy/references/frameworks.md#1-dfer--deprecate-fix-enforce-repeat)'s territory: freeze the current count as the CI baseline, fix incrementally as files get touched, then enforce once it's clean — not a one-off triage.

**"Should this run pre-commit or only in CI?"**
Both, tiered — see the automation-tiers table. The only reason to skip pre-commit is a check that's genuinely too slow to run on every commit (e.g. a full type-check on a huge monorepo); even then, run a fast subset pre-commit and the full check in CI, don't drop pre-commit entirely.

**"Nothing in our style guide is a mechanical rule — it's about naming conventions and 'is this the right abstraction'."**
That's exactly the boundary between linting and AI-assisted review. If it can't be expressed as a rule, it's not a linting gap — recommend a review skill/agent for that specific judgment call instead of forcing it into a linter config that will never quite capture it.

---

## The wrong tool for the right reason

The most common mistake: reaching for more tests when the actual gap is upstream — a bug pattern a linter or type checker would catch on every future occurrence, not just the one instance a new test covers. Prevention scales; a single regression test only prevents that one regression from recurring.

The second most common mistake: enabling every available rule at once on an existing codebase. It produces a wall of warnings nobody has time to fix, the linter gets muted or ignored, and the team ends up worse off than before — with a tool installed that catches nothing because nobody trusts its output anymore.

The third: replacing a tool that works because a faster or newer one exists, without a concrete pain point driving the migration. Automation should reduce cognitive load, not become a recurring source of churn.

## Execution — only with explicit authorization

If the user wants to check the current state of the repo right now, propose the exact command for the recommended tool (e.g. `eslint .`, `ruff check .`, `mypy .`, `golangci-lint run`) and run it only after the user explicitly confirms. Never run a command on your own initiative, and never run an autofix/mutating variant (`--fix`, `eslint --fix`, `ruff check --fix`) without a separate, explicit confirmation for that specific action.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.