Back to articles

Flutter project rules your AI agents cannot ignore

Every project I work on has a file like AGENTS.md: use the logger instead of print, feature code does not import the HTTP client, colours come from one place, widget files stay small. Humans forget these rules. Coding agents forget them faster, they are hard to enforce with simple skills or .md files.

An instruction is advice. A model can skip it, lose it halfway through a long task, or decide that this one case is the exception. I was reviewing the same mistakes every day, and my review was the only thing enforcing the rule.

A compiler error is different. Nobody argues with it, and agents clear errors before they say they are done. So the question became: how do I make my conventions look like compiler errors?

Writing an analyzer plugin in Dart for each rule was more work than most rules deserve. I wanted to write the rule in about the time it takes to write the AGENTS.md line. And I want an easier way for AIs to define those rules too.

What agent_lints does

agent_lints is a linter for Dart and Flutter where the rules live in a YAML file. One rule looks like this:

# agent_lints.yaml
version: 2
rules:
  no_print:
    severity: error
    use: print
    from: dart:core
    use_instead: AppLog.d(...)
    hint: "AppLog.d({{args.0}})"
    message: "`print` ships to release logs. Use {{use_instead}}."

The same rule runs in three places: the command line, dart analyze, and your editor, through the official analyzer plugin API. In the IDE it shows up as a real error with the severity you chose, so an agent sees it the same way it sees a type error.

Rules match the resolved code, not text. A widget created behind an import prefix is still that widget, and package:material_ui is treated like package:flutter.

On the command line the output is written for the agent that caused it:

[error] no_print  lib/features/home/home_screen.dart:19:5
  found    print('home loaded')
  why      `print` ships to release logs. Use AppLog.d(...).
  hint     AppLog.d('home loaded')
  ignore   // ignore: agent_lints/no_print -- <reason>

Every block says what was found, why it is wrong, what to paste instead. An agent reads that and fixes the code without opening a document.

What it looks like in a real app

I use it in Peggy, my expense tracker, to define the rules the project lives by and have agents follow them before their changes reach code review.

The first run found 63 raw colours and six oversized files, including a 1570-line settings page. An agent fixed all of it in one session: the colours moved into named constants, the big files were split into focused widgets, and the test suite stayed green. The IDE now complains the moment either rule is broken again.

Rules can be split by area, and it works the way include works in analysis_options.yaml: each included file is a complete config, merged in order.

# agent_lints.yaml
version: 2
include: [agent_lints/*.yaml]
files: [lib/**]

How to use it

Add it as a dev dependency, create the config, run it:

dart pub add --dev agent_lints
dart run agent_lints init
dart run agent_lints

For the IDE and dart analyze, enable the plugin in the root analysis_options.yaml and restart the analysis server. If a code generator in your project pins an older analyzer, this entry is all you need; the plugin resolves on its own.

plugins:
  agent_lints: ^0.3.0

Agents can write rules too. The explain command prints the rule language, validate reports every mistake in the YAML with a line number and a hint, and test runs the bad and good examples you attach to a rule. Running init with the --agents-md and --claude-skill flags writes that whole loop into your agent instructions.

Rules cover more than banned symbols: import layering, naming, constructor arguments, widget ancestry, file size, and design tokens with closest-value hints. The recipes page has ready-made ones to copy.

Contributing

The project is in active development and open: github.com/pedromassango/agent_lints.

There is a short list of open issues for the bigger things I have not built yet, like autofix and a watch mode. And if you sit down to write a rule and cannot get the YAML to say what you mean, tell me. That is the kind of bug I most want to hear about.

Write the rule once, and every agent/human on the project gets the project rules.

© 2026 Pedro Massango