tidy_imports 1.3.0
tidy_imports: ^1.3.0 copied to clipboard
Automatically organize your Dart imports. Sorts and groups dart, flutter, package, and project imports alphabetically. Spiritual successor to import_sorter.
████████╗██╗██████╗░██╗░░░██╗ ██╗███╗░░░███╗██████╗░░█████╗░██████╗░████████╗░██████╗
╚══██╔══╝██║██╔══██╗╚██╗░██╔╝ ██║████╗░████║██╔══██╗██╔══██╗██╔══██╗╚══██╔══╝██╔════╝
░░░██║░░░██║██║░░██║░╚████╔╝░ ██║██╔████╔██║██████╔╝██║░░██║██████╔╝░░░██║░░░╚█████╗░
░░░██║░░░██║██║░░██║░░╚██╔╝░░ ██║██║╚██╔╝██║██╔═══╝░██║░░██║██╔══██╗░░░██║░░░░╚═══██╗
░░░██║░░░██║██████╔╝░░░██║░░░ ██║██║░╚═╝░██║██║░░░░░╚█████╔╝██║░░██║░░░██║░░░██████╔╝
░░░╚═╝░░░╚═╝╚═════╝░░░░╚═╝░░░ ╚═╝╚═╝░░░░░╚═╝╚═╝░░░░░░╚════╝░╚═╝░░╚═╝░░░╚═╝░░░╚═════╝░
A Dart CLI tool that automatically organizes your import statements — sorted alphabetically and grouped by origin (Dart, Flutter, package, project).
Spiritual successor to import_sorter,
rebuilt for Dart 3+ with bug fixes, new flags, custom import tiers, pubspec.yaml
sorting, and monorepo support.
How it works #
Imports are grouped in this order and sorted alphabetically within each group:
- Dart imports (
dart:) - Flutter imports (
package:flutter/) - Package imports (
package:) - Project imports (relative or
package:<your_package>/)
Before #
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'dart:io';
import 'package:myapp/home.dart';
import 'dart:async';
import 'package:intl/intl.dart';
import 'another_file.dart';
After #
// Dart imports:
import 'dart:async';
import 'dart:io';
// Flutter imports:
import 'package:flutter/material.dart';
// Package imports:
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
// Project imports:
import 'package:myapp/home.dart';
import 'another_file.dart';
Installation #
As a dev dependency (per project) #
dart pub add dev:tidy_imports
dart run tidy_imports
This adds the latest version to dev_dependencies for you.
Global activation #
dart pub global activate tidy_imports
tidy_imports
Usage #
# Sort all dart files in the project
dart run tidy_imports
# Sort specific files
dart run tidy_imports lib/main.dart lib/app.dart
# Sort files matching a glob pattern
dart run tidy_imports "lib/src/*"
# Preview changes without writing (dry run)
dart run tidy_imports --dry-run
# CI: fail if any file is unsorted
dart run tidy_imports --exit-if-changed
Options #
| Flag | Short | Description |
|---|---|---|
--emojis |
-e |
Add emojis to import group comments |
--no-comments |
Omit group comments entirely | |
--no-blank-lines |
Omit blank lines between import groups | |
--sort-pubspec |
Also sort pubspec.yaml dependencies alphabetically |
|
--group-by-folder |
Separate project imports by subfolder | |
--test-imports |
Group project test doubles (fake_/mock_) separately |
|
--separate-relative-imports |
Blank line before relative imports, matching dart format (Dart 3.13+) |
|
--dry-run |
Preview changes without writing files | |
--exit-if-changed |
Exit with code 1 if any file would change | |
--ignore-config |
Ignore configuration file / pubspec.yaml block |
|
--version |
-v |
Print version and exit |
--help |
-h |
Show help |
Configuration #
Add a tidy_imports: block to your pubspec.yaml:
tidy_imports:
emojis: false # Default: false — add emojis to group comments
comments: true # Default: true — add group comments
blank_lines: true # Default: true — blank lines between groups
sort_pubspec: false # Default: false — also sort pubspec.yaml deps
group_project_by_folder: false # Default: false — split project imports by folder
separate_relative_imports: false # Default: false — blank line before relative imports
test_imports: false # Default: false — split fake_/mock_ files into their own group
test_import_prefixes: # Default: [fake_, mock_] — file-name prefixes treated as test doubles
- fake_
- mock_
ignored_files: # Regex patterns applied to relative file paths
- \/lib\/generated\/ # ignore a whole folder
- \.g\.dart$ # ignore generated files (build_runner)
- \.freezed\.dart$ # ignore freezed files
- \.gr\.dart$ # ignore auto_route files
tiers: # Custom import groups (see below)
- name: "Company imports:"
pattern: "package:acme_"
The ignored_files patterns are regular expressions matched against the path
relative to the project root (e.g. /lib/src/foo.dart).
Standalone config file #
Instead of the pubspec.yaml block, you can place the same options in a
tidy_imports.yaml file at the project root. When present, it takes precedence
over the pubspec.yaml block — handy for monorepos with a shared root config.
# tidy_imports.yaml
emojis: false
sort_pubspec: true
ignored_files:
- \.g\.dart$
Custom import tiers #
By default, all third-party packages share the single Package imports group. Custom tiers let you split out internal/shared packages into their own group, placed between the generic package group and your project imports:
tidy_imports:
tiers:
- name: "Shared imports:"
pattern: "package:acme_shared"
- name: "Company imports:"
pattern: "package:acme_"
Each import whose line contains a tier's pattern goes into that tier (first
match wins, so list the most specific patterns first). Result:
// Package imports:
import 'package:http/http.dart';
// Shared imports:
import 'package:acme_shared/utils.dart';
// Company imports:
import 'package:acme_billing/api.dart';
// Project imports:
import 'package:myapp/home.dart';
Sorting pubspec.yaml #
Pass --sort-pubspec (or set sort_pubspec: true) to also alphabetize the
dependencies, dev_dependencies, and dependency_overrides sections of your
pubspec.yaml. Nested dependency blocks (git/path/hosted) and comments attached
to a dependency are preserved.
dart run tidy_imports --sort-pubspec
Grouping project imports by folder #
Pass --group-by-folder (or set group_project_by_folder: true) to visually
separate your project imports by their subfolder with a blank line whenever the
folder changes — useful in large projects with many local files.
// Project imports:
import 'package:myapp/data/user_repository.dart';
import 'package:myapp/data/user_service.dart';
import 'package:myapp/ui/home_page.dart';
import 'package:myapp/ui/settings_page.dart';
Matching dart format (Dart 3.13+) #
Since Dart 3.13 the
formatter inserts a blank line between the package: and relative import
sections. Because tidy_imports keeps package:<your_project>/… and relative
imports together in one Project imports: block, the two tools used to undo
each other on every run.
Pass --separate-relative-imports (or set separate_relative_imports: true) to
emit that blank line up front, so both tools agree and the file stops flip-flopping:
// Project imports:
import 'package:myapp/home.dart';
import 'another_file.dart';
The option is a no-op when blank lines are disabled (--no-blank-lines /
blank_lines: false), and it never doubles up with --group-by-folder, which
already breaks at that boundary. It applies to the --test-imports group too.
Grouping test doubles #
Pass --test-imports (or set test_imports: true) to pull fakes and mocks out
of your project imports and into a dedicated group:
// Project imports:
import 'package:myapp/cliente_details_repository.dart';
// Test imports:
import 'package:myapp/mock_auth_service.dart';
import 'fake_cliente_details_repository.dart';
A file counts as a test double when it is a project import (relative or
package:<your_package>/) and its file name starts with a configured
prefix — fake_ or mock_ by default. Override the list with
test_import_prefixes (e.g. add stub_ or spy_); a custom list replaces the
defaults rather than extending them.
Third-party packages are never affected, so real pub packages whose names look
like doubles — package:fake_async/fake_async.dart,
package:mock_web_server/mock_web_server.dart — stay in Package imports.
To group testing libraries such as mockito, use a
custom tier instead:
tidy_imports:
test_imports: true
tiers:
- name: "Testing imports:"
pattern: "package:mockito"
CI Integration #
GitHub Actions #
- name: Check import order
run: dart run tidy_imports --exit-if-changed
--exit-if-changed checks the whole project in one pass and lists every
file that needs sorting before exiting with code 1 — so a single CI run shows
you everything to fix, not just the first offender. It never writes files. Use
--dry-run locally for the same read-only preview with a friendlier summary.
pre-commit hook #
# .pre-commit-config.yaml
repos:
- repo: https://github.com/Franklyn-R-Silva/tidy_imports
rev: 'v1.1.0' # use the latest release tag
hooks:
- id: dart-import-sorter # for plain Dart projects
# - id: flutter-import-sorter # for Flutter projects
Directories scanned #
lib/, src/, bin/, test/, tests/, test_driver/, integration_test/, packages/
The packages/ directory is included to support pub workspaces and monorepos.
Monorepo / pub workspace support #
tidy_imports works in pub workspaces where individual packages do not have their own pubspec.lock. When no lock file is found, the tool continues normally — Flutter plugin registrant detection is simply skipped. No crash, no manual workaround needed.
Improvements over import_sorter #
| Issue | import_sorter | tidy_imports |
|---|---|---|
| Arg parsing | Raw string matching — breaks with flags | ArgParser — correct flag resolution |
| Positional file args | Passes raw args (includes flags) |
Uses argResults.rest |
pubspec.lock in monorepos |
Crashes with PathNotFoundException |
Graceful fallback |
packages/ folder |
Not scanned | Scanned |
--dry-run preview |
Not available | Available |
--no-blank-lines |
Not available | Available |
| Custom import tiers | Not available | Available |
Sort pubspec.yaml deps |
Not available | --sort-pubspec |
| Group project imports by folder | Not available | --group-by-folder |
| Separate group for test doubles | Not available | --test-imports |
dart format 3.13+ import sections |
Fights the formatter | --separate-relative-imports |
| Invalid file pattern | Unhandled FormatException |
Readable error, exit 1 |
| Group comments inside string literals | Silently deleted | Preserved |
| Standalone config file | Not available | tidy_imports.yaml |
| Direct CLI command | dart pub global run ...:main |
tidy_imports |
--exit-if-changed in CI |
Aborts on first unsorted file | Reports every unsorted file |
| pre-commit hook | language: script (broken) |
language: system (works) |
| Dart SDK | >=2.12.0 |
>=3.0.0 |
| Conditional imports | Misclassified | Handled correctly |
| Versioning | Manual | Automated via Release Please |
Contributing #
Pull requests are welcome! See CONTRIBUTING.md for dev setup, commit format, and the release process.
Credits #
Based on the original work by @gleich and contributors of import_sorter.
License #
MIT © Franklyn R. Silva