zed-industries/zed

lint-creator

Add, modify, or test a custom dylint lint in `tooling/lints`.

First seen Jul 18, 2026

Installation

$ npx skills add zed-industries/zed --skill lint-creator

Summary

  • Add, modify, or test a custom dylint lint in `tooling/lints`.
  • Covers the module/registration layout, UI test conventions (including negative tests and the gpui test fixture), how to run tests with the crate's pinned nightly and update `.stderr` files, and how to validate a lint against the real codebase with `single-lint`.
  • Use whenever the user asks to write a new lint or debug an existing one.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from zed-industries/zed.

npx skills add zed-industries/zed

Browse all from zed-industries/zed

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 90.0K
License LICENSE-APACHE
Default branch main
Open issues 2,471
Status Active

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 3,475 B
  • docs SUMMARY.md 417 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2 installs

SKILL.md

Adding a dylint to tooling/lints

Before writing anything

  1. Check whether clippy already covers the pattern (search https://rust-lang.github.io/rust-clippy/master/). If it does, stop and report that to the user instead of writing a redundant lint.

Layout

  • One module per lint: src/<lint_name>.rs, declared in src/lib.rs.
  • Register the lint in registerlints in src/lib.rs: add it to the lintstore.registerlints(&[...]) slice and add a registerlate_pass call.
  • Use src/notifyinrender.rs as the template: rustcsession::declarelint! with ### What it does / ### Why is this bad? doc sections, impllintpass!, and a LateLintPass impl that bails early with let ... else / early returns.
  • Do NOT copy the diagnostics style of sharedstringfromstrliteral in lib.rs — it predates the rules below (it emits a machine-applicable suggestion). The two lints living directly in lib.rs also predate the one-module-per-lint rule.
  • Reuse the helpers in src/renderhelpers.rs (isdirectlyinrendermethod, isgpui_context) for render/gpui checks.

Diagnostics rules

  • Flag only; never suggest how to fix, and never use Applicability::MachineApplicable.
  • Keep detection and reporting as simple as possible: prefer spanlint with a one-sentence message over spanlintandthen with notes.
  • Skip macro-expanded code (expr.span.from_expansion()).

UI tests (required)

  • Every lint needs ui/<lintname>.rs and ui/<lintname>.stderr.
  • The .rs file must include negative cases: code that resembles the bad pattern but must produce no diagnostic. Their absence from the .stderr file is the assertion.
  • UI tests that need gpui types use the fake gpui crate in testfixture/ (wired up by gpuifixturerustcflags in lib.rs). Extend the fixture if a type or method is missing — never add real gpui as a dependency.
  • The crate is deliberately not part of the zed workspace and pins its own nightly (rust-toolchain.toml). Run tests from inside the crate:

`` cd tooling/lints && cargo test ``

  • To update a .stderr file after an intentional change: run the test, find the Actual stderr saved to PATH line in the failure report, and copy that file over the checked-in .stderr. There is no bless env var. A correct .stderr typically ends with one blank line.

After the lint works

  • Add the lint to the "Current lints" list in tooling/lints/README.md.
  • Smoke-test it against the real codebase:

`` tooling/lints/single-lint <lint_name> -p <crate> ``

(defaults to --workspace if no package is given; the script handles the --force-warn and cache-cleaning gotchas documented in the README).

UI fixture sections

Every lint-specific ui/*.rs fixture MUST put cases expected to trigger the lint first, followed by cases expected not to trigger it, using exactly these headings:

// ==================== SHOULD FIRE ====================
// ================== SHOULD NOT FIRE ==================